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

Flutter Camera插件:如何将拍摄方向锁定为landscapeRight或landscapeLeft?

Flutter Camera插件横屏双方向适配方案

你的问题核心是lockCaptureOrientation固定单一方向后,另一种横屏模式下相机流与UI方向不匹配。解决方案是根据设备实时横屏方向动态调整相机捕获方向,而非锁定单一方向,具体实现如下:

1. 监听设备方向变化,动态锁定相机捕获方向

通过Flutter原生的方向监听机制,在设备切换横屏方向时,同步更新相机的捕获方向:

class CameraScreen extends StatefulWidget {
  const CameraScreen({super.key});

  @override
  State<CameraScreen> createState() => _CameraScreenState();
}

class _CameraScreenState extends State<CameraScreen> with WidgetsBindingObserver {
  CameraController? _controller;
  DeviceOrientation? _currentOrientation;

  @override
  void initState() {
    super.initState();
    _initCamera();
    // 注册方向变化监听
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    // 移除监听,避免内存泄漏
    WidgetsBinding.instance.removeObserver(this);
    _controller?.dispose();
    super.dispose();
  }

  // 监听设备方向变化
  @override
  void didChangeMetrics() {
    super.didChangeMetrics();
    final currentDeviceOrientation = WidgetsBinding.instance.window.orientation;
    // 仅处理横屏方向的切换
    if ([DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight].contains(currentDeviceOrientation)) {
      if (currentDeviceOrientation != _currentOrientation) {
        _currentOrientation = currentDeviceOrientation;
        // 动态更新相机捕获方向
        _controller?.lockCaptureOrientation(currentDeviceOrientation);
        setState(() {});
      }
    }
  }

  // 初始化相机控制器
  Future<void> _initCamera() async {
    final cameras = await availableCameras();
    final targetCamera = cameras.first; // 根据需求选择前置/后置相机
    _controller = CameraController(
      targetCamera,
      ResolutionPreset.high,
    );

    await _controller?.initialize();
    // 初始化时锁定当前设备横屏方向
    final initialOrientation = WidgetsBinding.instance.window.orientation;
    if ([DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight].contains(initialOrientation)) {
      _currentOrientation = initialOrientation;
      await _controller?.lockCaptureOrientation(initialOrientation);
    }
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    if (_controller == null || !_controller!.value.isInitialized) {
      return const Center(child: CircularProgressIndicator());
    }
    return AspectRatio(
      aspectRatio: _controller!.value.aspectRatio,
      child: CameraPreview(_controller!),
    );
  }
}

2. 保持main函数的横屏设置不变

继续保留你原来的全局横屏配置,确保应用仅允许横屏模式:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await SystemChrome.setPreferredOrientations([
    DeviceOrientation.landscapeRight,
    DeviceOrientation.landscapeLeft,
  ]);
  runApp(const MyApp());
}

关键说明

  • 该方案会在设备切换横屏方向时,自动同步相机的捕获方向,保证相机流与UI方向一致,两种横屏模式均能正常工作。
  • 建议在真实设备上测试,模拟器的方向切换可能存在延迟或异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 20:35:16