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

Flutter中如何让CustomPaint覆盖Camera Preview?

解决CustomPaint显示在CameraPreview下方的问题

我明白你遇到的困扰了——你想让自定义绘制的内容显示在相机预览的上方,但现在它被相机预览给挡住了。这是因为你把CameraPreview作为CustomPaint的child,而CustomPaint的painter属性是在child的底层进行绘制的,所以相机预览层会覆盖掉你画的红线。

这里有两种简单的解决办法:

方法1:使用CustomPaint的foregroundPainter属性

CustomPaint提供了foregroundPainter属性,它会在child的上层进行绘制,刚好符合你的需求。只需要把原来的painter替换成foregroundPainter就行:

class _CameraPreviewState extends State<CameraPreview> { 
  [...] 
  Widget build(BuildContext context) { 
    double height = MediaQuery.of(context).size.height; 
    return YidKitTheme(
      child: Center(
        child: _isReady ? Container(
          height: height / 2,
          child: CustomPaint(
            // 把painter换成foregroundPainter
            foregroundPainter: GuidelinePainter(), 
            child: AspectRatio(
              aspectRatio: controller.value.aspectRatio,
              child: CameraPreview(controller)
            ), 
          ) 
        ) : CircularProgressIndicator() 
      ) 
    ); 
  } 
}

class GuidelinePainter extends CustomPainter { 
  @override 
  void paint(Canvas canvas, Size size) { 
    Paint paint = Paint() 
      ..strokeWidth = 3.0 
      ..color = Colors.red 
      ..style = PaintingStyle.stroke; 
    var path = Path()..lineTo(50.0, 50.0); 
    canvas.drawPath(path, paint); 
  } 

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

方法2:用Stack组件叠加层级

如果后续你需要更灵活地控制各个组件的位置和层级,用Stack是更好的选择。把CameraPreview放在Stack的底层,CustomPaint放在上层:

class _CameraPreviewState extends State<CameraPreview> { 
  [...] 
  Widget build(BuildContext context) { 
    double height = MediaQuery.of(context).size.height; 
    return YidKitTheme(
      child: Center(
        child: _isReady ? Container(
          height: height / 2,
          child: Stack(
            children: [
              // 底层放相机预览
              AspectRatio(
                aspectRatio: controller.value.aspectRatio,
                child: CameraPreview(controller)
              ),
              // 上层放自定义绘制
              CustomPaint(
                painter: GuidelinePainter(),
                // 让CustomPaint占满整个父容器的大小
                size: Size.infinite,
              )
            ],
          )
        ) : CircularProgressIndicator() 
      ) 
    ); 
  } 
}

// GuidelinePainter代码保持不变
class GuidelinePainter extends CustomPainter { 
  @override 
  void paint(Canvas canvas, Size size) { 
    Paint paint = Paint() 
      ..strokeWidth = 3.0 
      ..color = Colors.red 
      ..style = PaintingStyle.stroke; 
    var path = Path()..lineTo(50.0, 50.0); 
    canvas.drawPath(path, paint); 
  } 

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

两种方法都能解决你的问题,你可以根据自己的需求选择。如果只是简单的上层绘制,方法1更简洁;如果需要复杂的布局,方法2更灵活。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:31:54