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

Flutter CameraPreview画面旋转90度且拉伸变形问题求助

解决CameraPreview画面旋转拉伸问题

问题原因

  1. lockCaptureOrientation仅控制拍摄后照片的保存方向,不影响预览的显示方向,预览的方向匹配需要结合相机传感器方向和布局约束处理。
  2. 直接用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 12:34:59