Flutter CameraPreview画面旋转90度且拉伸变形问题求助
解决CameraPreview画面旋转拉伸问题
问题原因
lockCaptureOrientation仅控制拍摄后照片的保存方向,不影响预览的显示方向,预览的方向匹配需要结合相机传感器方向和布局约束处理。- 直接用Flexible的flex比例强制分配空间,会让CameraPreview被拉伸,没有遵循相机原生预览分辨率的宽高比(相机传感器通常默认是横屏输出,竖屏场景下需要交换宽高计算比例)。
解决方案
1. 初始化相机时获取正确的预览宽高比
在初始化CameraController后,根据设备横竖屏状态,结合相机的预览分辨率计算正确的宽高比:
late CameraController _controller; late Future<void> _initializeControllerFuture; late double _previewAspectRatio; @override void initState() { super.initState(); _initializeCamera(); } void _initializeCamera() async { final cameras = await availableCameras(); _controller = CameraController( cameras.first, ResolutionPreset.ultraHigh, enableAudio: false, )..lockCaptureOrientation(DeviceOrientation.portraitDown); // 保留照片方向锁定 _initializeControllerFuture = _controller.initialize().then((_) { final previewSize = _controller.value.previewSize!; // 根据设备方向调整宽高比:竖屏时交换相机预览的宽高 final isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; _previewAspectRatio = isPortrait ? previewSize.height / previewSize.width : previewSize.width / previewSize.height; setState(() {}); }); }
2. 用AspectRatio包裹CameraPreview强制比例
通过AspectRatio组件约束CameraPreview的显示比例,避免拉伸:
return Scaffold( body: SafeArea( child: Column( mainAxisSize: MainAxisSize.min, children: <Widget>[ Flexible( flex: 7, child: ClipRRect( borderRadius: BorderRadius.circular(15), child: FutureBuilder<void>( future: _initializeControllerFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { return AspectRatio( aspectRatio: _previewAspectRatio, child: CameraPreview( _controller, key: const Key('CameraPreview'), ), ); } else { return const Center(child: CircularProgressIndicator()); } }, ), ), ), // 其他操作控件... ], ), ), );
3. 处理设备方向变化(可选)
如果需要支持横竖屏切换,监听设备方向变化并更新宽高比:
@override void didChangeDependencies() { super.didChangeDependencies(); if (_controller.value.isInitialized) { final previewSize = _controller.value.previewSize!; final isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; final newRatio = isPortrait ? previewSize.height / previewSize.width : previewSize.width / previewSize.height; if (newRatio != _previewAspectRatio) { setState(() => _previewAspectRatio = newRatio); } } }
额外提示
你使用的camera插件0.11.0+1版本较旧,如果上述方案仍有问题,建议升级到最新稳定版(如camera 0.13.x),新版本对预览方向、宽高比的适配逻辑更完善,同时注意升级时的API兼容性调整。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

