You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中如何创建带有透明孔洞的Widget?

在Flutter任意Widget上创建透明孔洞的实现方案

你需要的是在Stack上层的任意Widget(而非单色遮罩)上挖洞,露出下层Widget的效果。Flutter中没有直接的WidgetFiltered组件,但可以通过**图层混合模式(BlendMode)**结合CustomPaint或Stack实现需求,以下是具体方案:


方案1:Stack + CustomPaint(支持任意上层Widget挖洞)

这个方案适用于上层是复杂Widget(比如带布局、文字的组合组件)的场景,通过在最上层叠加清除像素的绘制层来挖洞。

实现代码

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

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        // 下层:需要显示的底层内容
        Image.asset(
          "images/flutter.jpg",
          fit: BoxFit.cover,
          width: double.infinity,
          height: double.infinity,
        ),
        // 上层:需要挖洞的任意Widget(这里用带文字的半透明遮罩示例)
        Container(
          color: Colors.black.withOpacity(0.6),
          alignment: Alignment.center,
          child: const Text(
            "上层复杂Widget",
            style: TextStyle(color: Colors.white, fontSize: 28, fontWeight: FontWeight.bold),
          ),
        ),
        // 挖洞层:清除对应区域像素,露出底层
        CustomPaint(
          painter: HolePainter(),
          size: Size.infinite,
        ),
      ],
    );
  }
}

class HolePainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final clearPaint = Paint()..blendMode = BlendMode.clear;
    
    // 绘制圆形孔洞(可替换为矩形、路径等任意形状)
    canvas.drawCircle(
      Offset(size.width / 2, size.height / 2),
      80,
      clearPaint,
    );
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

方案2:适配你提供的CustomPaint三层结构

针对你给出的CustomPaint分层绘制示例,可以修改前景绘制逻辑,在前景层挖洞露出中间的child内容:

实现代码

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,
      ),
      // 背景层:蓝色半透明遮罩
      painter: LayerPainter(Colors.blue.withOpacity(0.5)),
      // 前景层:红色半透明遮罩 + 挖洞
      foregroundPainter: HoleLayerPainter(Colors.red.withOpacity(0.5)),
      size: const Size.square(200.0),
      willChange: true,
    );
  }
}

class LayerPainter extends CustomPainter {
  final Color layerColor;

  LayerPainter(this.layerColor);

  @override
  void paint(Canvas canvas, Size size) {
    canvas.drawRect(
      Offset.zero & size,
      Paint()..color = layerColor,
    );
  }

  @override
  bool shouldRepaint(covariant LayerPainter oldDelegate) => oldDelegate.layerColor != layerColor;
}

class HoleLayerPainter extends CustomPainter {
  final Color layerColor;

  HoleLayerPainter(this.layerColor);

  @override
  void paint(Canvas canvas, Size size) {
    // 先绘制前景遮罩
    canvas.drawRect(
      Offset.zero & size,
      Paint()..color = layerColor,
    );
    // 用clear模式挖洞
    final clearPaint = Paint()..blendMode = BlendMode.clear;
    canvas.drawCircle(
      Offset(size.width / 2, size.height / 2),
      60,
      clearPaint,
    );
  }

  @override
  bool shouldRepaint(covariant HoleLayerPainter oldDelegate) => oldDelegate.layerColor != layerColor;
}

核心说明

  • 实现挖洞的关键是BlendMode.clear:该混合模式会清除画布对应区域的像素,从而让下层内容透出来。
  • 支持任意形状的孔洞:只需在CustomPainter中替换绘制逻辑(比如用drawRect画矩形洞、drawPath画不规则洞)。
  • 平台兼容注意:BlendMode.clear在Web平台可能需要开启Skia渲染,移动端可直接使用。

内容的提问来源于stack exchange,提问作者Lebecca

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 13:54:21