Flutter使用Texture渲染相机预览画面拉伸如何解决?
Flutter 基于Texture实现相机预览的拉伸变形适配方案
问题背景
直接使用Texture组件承载相机预览流时,错误设置容器宽高比会导致画面严重拉伸,原有问题代码如下:
final size = MediaQuery.of(context).size; final deviceRatio = size.width / size.height; return Align( alignment: Alignment.topCenter, child: AspectRatio( aspectRatio: deviceRatio, child: Stack( children: <Widget>[ CustomPaint( foregroundPainter: MeasureFaceOutline(isPosCorrect: true), child: Transform( alignment: Alignment.center, transform: Platform.isIOS ? Matrix4.rotationX(math.pi) : Matrix4.identity(), child: Texture(textureId: textureId), ), ), ], ), ), ); }
已知对照场景:使用官方CameraPreview组件搭配1.7倍缩放时,预览画面显示完全正常,但业务场景要求必须直接使用Texture组件实现预览,需无变形适配方案。
问题根因
画面拉伸的核心原因是错误使用设备屏幕宽高比作为Texture父容器的宽高比,没有对齐相机传感器实际输出的预览帧比例。当容器比例和纹理输出比例不一致时,Texture会默认拉伸填满父容器,直接导致变形。
官方CameraPreview组件本身也是基于Texture封装,内部已经做了比例对齐、动态缩放、裁剪的适配逻辑,我们直接在Texture层复用这套逻辑即可,不需要依赖CameraPreview组件。
适配实现步骤
- 第一步:获取相机真实输出比例
相机初始化完成后,从相机控制器实例中读取预览尺寸,计算真实宽高比。注意竖屏场景下Android和iOS平台的预览尺寸宽高方向可能倒置,计算时根据实际显示效果调整宽高顺序即可:// 相机初始化完成后取值,不要在初始化未完成时读取 final previewSize = controller!.value.previewSize!; // 竖屏场景下如果比例异常,就把宽高反过来计算:previewSize.height / previewSize.width final cameraPreviewRatio = previewSize.width / previewSize.height; - 第二步:动态计算缩放值,替代硬编码的1.7倍缩放
不要写死缩放参数,根据屏幕比例和相机预览比例动态计算缩放值,保证画面铺满目标区域的同时不出现比例变形:final screenSize = MediaQuery.of(context).size; final screenRatio = screenSize.width / screenSize.height; final scale = screenRatio / cameraPreviewRatio; final finalScale = scale < 1 ? 1 / scale : scale; - 第三步:调整布局结构,增加裁剪逻辑
替换原有基于设备比例的AspectRatio配置,外层增加裁剪容器避免缩放后的画面溢出遮挡其他组件,完整可运行代码如下:return Align( alignment: Alignment.topCenter, child: ClipRect( child: Transform.scale( scale: finalScale, alignment: Alignment.center, child: AspectRatio( aspectRatio: cameraPreviewRatio, child: Stack( children: <Widget>[ CustomPaint( foregroundPainter: MeasureFaceOutline(isPosCorrect: true), child: Transform( alignment: Alignment.center, transform: Platform.isIOS ? Matrix4.rotationX(math.pi) : Matrix4.identity(), child: Texture(textureId: textureId), ), ), ], ), ), ), ), );
适配说明:上述实现逻辑和官方CameraPreview内部的适配逻辑完全一致,不需要引入CameraPreview组件,直接使用Texture即可实现无拉伸、无变形的预览效果,和之前测试正常的缩放版CameraPreview显示效果完全对齐。如果需要适配横屏场景,只需要同步调整预览比例的宽高计算顺序即可。
内容的提问来源于stack exchange,提问作者Captivity
相关产品推荐
相关产品推荐

