Flutter(Dart):将屏幕分成 6 部分,每一部分有一个角在中心

sti*_*ale 2 dart flutter flutter-layout

我试图将屏幕分成 6 个部分/部分,并满足以下要求:

  • 每个部分都应该在屏幕中心有一个角(连接到示例图中的中心圆,见下文)。
  • 每个部分都应连接到屏幕的周边。

我想在每个部分都有一个单独的 GestureDetector。

有谁知道使用 Flutter 和 Dart 实现此目的的好方法吗?

示例图

链接到示例图

Md.*_*ikh 8

对于内圈,我正在使用ContainerStack放置这些小部件。形状是用 制成的ClipPath

利用将圆形按钮放置为最后一个堆栈子项,因为 UI 优先从下到上,

在dartpad上运行。

路径

class BottomCentertPath extends CustomClipper<Path> {
  @override
  Path getClip(Size size) => Path()
    ..moveTo(size.width / 4, size.height)
    ..lineTo(size.width / 4 * 3, size.height)
    ..lineTo(size.width / 2, size.height / 2);

  @override
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) => false;
}

class BottomLeftPath extends CustomClipper<Path> {
  @override
  Path getClip(Size size) => Path()
    ..moveTo(size.width, size.height / 3 * 2)
    ..lineTo(size.width, size.height)
    ..lineTo(size.width / 4 * 3, size.height)
    ..lineTo(size.width / 2, size.height / 2);

  @override
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) => false;
}

class BottomRightPath extends CustomClipper<Path> {
  @override
  Path getClip(Size size) => Path()
    ..moveTo(0, size.height / 3 * 2)
    ..lineTo(0, size.height)
    ..lineTo(size.width / 4, size.height)
    ..lineTo(size.width / 2, size.height / 2);

  @override
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) => false;
}

class CenterRighttPath extends CustomClipper<Path> {
  @override
  Path getClip(Size size) => Path()
    ..moveTo(size.width, size.height / 3)
    ..lineTo(size.width / 2, size.height / 2)
    ..lineTo(size.width, size.height / 3 * 2);

  @override
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) => false;
}

class CenterLeftPath extends CustomClipper<Path> {
  @override
  Path getClip(Size size) => Path()
    ..moveTo(0, size.height / 3)
    ..lineTo(size.width / 2, size.height / 2)
    ..lineTo(0, size.height / 3 * 2);

  @override
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) => false;
}

class TopRightPath extends CustomClipper<Path> {
  @override
  Path getClip(Size size) => Path()
    ..moveTo(size.width / 2, 0)
    ..lineTo(size.width, 0)
    ..lineTo(size.width, size.height / 3)
    ..lineTo(size.width / 2, size.height / 2);

  @override
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) => false;
}

class TopLeftPath extends CustomClipper<Path> {
  @override
  Path getClip(Size size) => Path()
    ..lineTo(size.width / 2, 0)
    ..lineTo(size.width / 2, size.height / 2)
    ..lineTo(0, size.height / 3);

  @override
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) => false;
}
Run Code Online (Sandbox Code Playgroud)

测试小工具


class S7venIn1 extends StatelessWidget {
  const S7venIn1({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: LayoutBuilder(builder: (context, constraints) {
        return Stack(
          children: [
            GestureDetector(
              onTap: () {
                debugPrint("TopLeftPath:");
              },
              child: ClipPath(
                clipper: TopLeftPath(),
                child: Container(
                  color: Colors.cyanAccent,
                ),
              ),
            ),
            GestureDetector(
              onTap: () {
                debugPrint("TopRightPath:");
              },
              child: ClipPath(
                clipper: TopRightPath(),
                child: Container(
                  color: Colors.deepPurple,
                ),
              ),
            ),
            GestureDetector(
              onTap: () {
                debugPrint("CenterLeftPath:");
              },
              child: ClipPath(
                clipper: CenterLeftPath(),
                child: Container(
                  color: Colors.deepOrange,
                ),
              ),
            ),
            ClipPath(
              clipper: CenterRighttPath(),
              child: Container(
                color: Colors.greenAccent,
              ),
            ),
            GestureDetector(
              onTap: () {
                debugPrint("CenterRighttPath:");
              },
              child: ClipPath(
                clipper: CenterRighttPath(),
                child: Container(
                  color: Colors.greenAccent,
                ),
              ),
            ),
            GestureDetector(
              onTap: () {
                debugPrint("BottomRightPath");
              },
              child: ClipPath(
                clipper: BottomRightPath(),
                child: Container(
                  color: Colors.indigoAccent,
                ),
              ),
            ),
            GestureDetector(
              onTap: () {
                debugPrint("BottomCentertPath");
              },
              child: ClipPath(
                clipper: BottomCentertPath(),
                child: Container(
                  color: Colors.pinkAccent,
                ),
              ),
            ),
            GestureDetector(
              onTap: () {
                debugPrint("BottomLeftPath");
              },
              child: ClipPath(
                clipper: BottomLeftPath(),
                child: Container(
                  color: Colors.amberAccent,
                ),
              ),
            ),
            Align(
              alignment: Alignment.center,
              child: GestureDetector(
                onTap: () {
                  debugPrint("Center Widget");
                },
                child: Container(
                  height: constraints.maxWidth * .25,
                  decoration: const BoxDecoration(
                      shape: BoxShape.circle, color: Colors.white),
                ),
              ),
            )
          ],
        );
      }),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

玩转尺寸CustomClipper<Path>。检查此内容以了解更多信息。

结果

在此输入图像描述