Flutter相机画面拉伸变形问题求助
解决Flutter Camera预览画面拉伸变形的问题
嘿,我之前也踩过这个坑!用camera包的时候默认的预览逻辑很容易因为强制适配屏幕尺寸导致画面拉伸失真,其实核心就是要让相机预览的输出比例和屏幕比例匹配,再通过布局控件处理铺满屏幕的逻辑,下面是具体的实现步骤:
1. 筛选与屏幕比例匹配的相机预览尺寸
相机硬件支持的预览尺寸是固定的一组值,不能随便自定义,所以第一步要从相机支持的尺寸里挑出和当前屏幕比例最接近的那个:
// 获取当前屏幕的宽高比 final screenSize = MediaQuery.of(context).size; final screenAspectRatio = screenSize.width / screenSize.height; // 获取相机描述(假设你已通过camera包拿到cameraDescription) // 注意:根据传感器方向,需要互换宽高计算比例(竖屏时传感器通常是横置的) final previewSizes = cameraDescription.sensorOrientation == 90 || cameraDescription.sensorOrientation == 270 ? cameraDescription.previewSizes.map((size) => Size(size.height, size.width)).toList() : cameraDescription.previewSizes.map((size) => Size(size.width, size.height)).toList(); // 筛选出比例最接近屏幕的预览尺寸 Size? bestPreviewSize; double minRatioDifference = double.infinity; for (final size in previewSizes) { final previewRatio = size.width / size.height; final difference = (previewRatio - screenAspectRatio).abs(); if (difference < minRatioDifference) { minRatioDifference = difference; bestPreviewSize = size; } }
2. 初始化CameraController时指定最佳预览尺寸
拿到合适的预览尺寸后,初始化控制器的时候把它传进去,让相机输出对应比例的画面:
final cameraController = CameraController( cameraDescription, ResolutionPreset.medium, // 可根据需求选择预设,若筛选不到合适尺寸可尝试更高预设(如high) previewSize: bestPreviewSize, // 关键:设置我们筛选出的最佳尺寸 ); await cameraController.initialize();
3. 用布局控件实现无拉伸铺满屏幕
最后在布局的时候,通过FittedBox+ClipRect组合,让预览画面保持比例的同时铺满屏幕(超出屏幕的部分会被裁剪,和原生相机逻辑一致):
Container( width: double.infinity, height: double.infinity, child: ClipRect( child: OverflowBox( alignment: Alignment.center, child: FittedBox( fit: BoxFit.cover, child: SizedBox( width: bestPreviewSize!.width, height: bestPreviewSize!.height, child: CameraPreview(cameraController), ), ), ), ), )
额外注意事项
- 不要硬编码比例:不同设备的屏幕比例、相机支持的尺寸都不一样,必须动态筛选才能适配所有机型。
- 传感器方向处理:如果忽略传感器方向直接计算比例,在竖屏模式下很容易出现比例错误,导致画面被压扁或拉长。
- 权限与初始化:确保已经申请了相机权限,并且在控制器初始化完成后再渲染预览画面。
这样调整之后,你的相机预览应该就会和原生相机一样,保持正确的比例且铺满屏幕,不会再出现拉伸变形的问题啦!
内容的提问来源于stack exchange,提问作者Angus Allman




