flutter - 如何在 flutter 中创建带有透明孔的小部件

标签 flutter dart canvas flutter-layout

我想在任何 Flutter 小部件中创建一个洞。例如,假设我们在一个堆栈中有两个小部件,我想在上面的一个小部件上挖一个洞,以使下面的小部件对用户可见。

有一个question具有相似的标题,但接受的答案与问题不完全匹配。答案是在单色覆盖层上挖一个洞,而不是在一个完整的小部件上。

我发现使用CustomPaint我们可以在三层中绘制小部件:

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

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      child: Image.asset(
        "images/flutter.jpg",
        fit: BoxFit.cover,
      ),
      foregroundPainter: DemoPainter(Colors.red.withOpacity(0.5)),
      painter: DemoPainter(Colors.blue.withOpacity(0.5)),
      size: Size.square(200.0),
      willChange: true,
    );
  }
}

但是我找不到像上面答案中提到的 ColorFiltered 这样的机制。是否有一种叫做 WidgetFiltered 的东西,作为小部件世界中单色覆盖世界的对应物,我们可以用它来处理两个重叠小部件的渲染(例如,示例代码)?

最佳答案

我正在使用ClipPath,而包含的答案已使用ColorFilter

更改 slider 值以更改孔尺寸

运行于 dartPad

class WidgetHole extends StatefulWidget {
  const WidgetHole({Key? key}) : super(key: key);

  @override
  State<WidgetHole> createState() => _WidgetHoleState();
}

class _WidgetHoleState extends State<WidgetHole> {
  double dimension = 52;

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) => Scaffold(
        backgroundColor: Colors.pink,
        appBar: AppBar(
          backgroundColor: Colors.purple,
          title: Slider(
            value: dimension,
            max: constraints.maxWidth,
            onChanged: (v) {
              setState(() {
                dimension = v;
              });
            },
          ),
        ),
        body: ClipPath(
          clipper: CenterHolePath(dimension: dimension),
          child: Container(
            alignment: Alignment.center,
            color: Colors.yellow,
            child: Column(
              children: [
                Text("Hey this is background"),
                Expanded(
                    child: ListView.builder(
                  clipBehavior: Clip.hardEdge,
                  itemCount: 44,
                  itemBuilder: (context, index) {
                    return Center(
                      child: SizedBox(
                        height: kToolbarHeight,
                        child: Text("lItem  $index"),
                      ),
                    );
                  },
                ))
              ],
            ),
          ),
        ),
      ),
    );
  }
}

class CenterHolePath extends CustomClipper<Path> {
  final double dimension;
  CenterHolePath({
    required this.dimension,
  });

  @override
  Path getClip(Size size) {
    final rect = Rect.fromLTRB(0, 0, size.width, size.height);

    final path = Path()
      ..fillType = PathFillType.evenOdd
      ..addOval(
        Rect.fromCenter(
            center: Offset(size.width / 2, size.height / 2),
            width: dimension,
            height: dimension),
      )
      ..addRect(rect);

    return path;
  }

  @override
  bool shouldReclip(covariant CenterHolePath oldClipper) {
    return dimension != oldClipper.dimension;
  }
}

粉色是脚手架背景

enter image description here

关于flutter - 如何在 flutter 中创建带有透明孔的小部件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73068502/

相关文章:

Flutter:从 GestureDetector 获取本地位置

flutter - 如何添加要在收藏夹页面上显示的项目?

javascript - HTML 5 如何记录过滤的 Canvas

html - Canvas 中沿曲线的渐变描边

flutter - 云消息主题订阅是否持续存在?

flutter - 如何将 ListView 添加到 Flutter 中的列?

dart - 在 _MaterialAppState 中找不到路由 "home-page"的生成器

dart - 缺少方法 "null"。 smoke 包的代码生成似乎不完整

flutter - 如果我离线,如何下载flutter软件包以使用它?

java - 将 TextView 转换为位图返回 null