【问题标题】:Take camera picture in landscape and portrait with rotation disabled in Flutter在 Flutter 中禁用旋转以横向和纵向拍摄相机照片
【发布时间】:2021-11-22 13:15:10
【问题描述】:

我想构建一个屏幕,让我可以横​​向和纵向拍摄照片。我的应用程序仅通过在 main 中调用以下命令以纵向模式运行:

等待 SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);

由于我的屏幕不再旋转,因此即使我将手机倾斜到一边,图像也始终是纵向拍摄的。这是一个小示例项目,您可以清楚地看到它:

import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
import 'package:flutter/services.dart';

List<CameraDescription> cameras = [];

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
  cameras = await availableCameras();
  runApp(CameraApp());
}

class CameraApp extends StatefulWidget {
  @override
  _CameraAppState createState() => _CameraAppState();
}

class _CameraAppState extends State<CameraApp> {
  CameraController? controller;
  bool takingPicture = false;
  XFile? selectedImage;

  @override
  void initState() {
    super.initState();
    controller = CameraController(cameras[0], ResolutionPreset.max);
    controller!.initialize().then((_) {
      if (!mounted) {
        return;
      }
      setState(() {});
    });
  }

  @override
  void dispose() {
    controller?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    if (!controller!.value.isInitialized) {
      return Container();
    }
    return MaterialApp(
      home: Stack(
        fit: StackFit.expand,
        children: [
          RotatedBox(
            quarterTurns: 1 - controller!.description.sensorOrientation ~/ 90,
            child: CameraPreview(controller!),
          ),
          CameraPreview(controller!),
          Align(
            alignment: Alignment.bottomRight,
            child: FloatingActionButton(
              onPressed: () {
                if (!takingPicture) {
                  takingPicture = true;
                  controller!.takePicture().then(
                    (value) {
                      selectedImage = value;
                      setState(() {});
                      takingPicture = false;
                    },
                  );
                }
              },
            ),
          ),
          Align(
            alignment: Alignment.bottomLeft,
            child: selectedImage != null
                ? Container(
                    height: 100,
                    width: 200,
                    child: Image.file(
                      File(selectedImage!.path),
                    ),
                  )
                : Container(),
          ),
        ],
      ),
    );
  }
}

旋转手机并拍照时,照片也应该以横向显示,但事实并非如此。如何在不使用 setPreferredOrientations 的情况下解决此问题?

Android 和 iOS 上的普通移动应用也可以做到这一点。

【问题讨论】:

    标签: android ios flutter dart camera


    【解决方案1】:

    我要做的是在进入屏幕时删除约束并在进入时重新应用它。

    这是一个改编自您的代码的示例,其中包含 2 个屏幕:

    • 无法旋转的欢迎屏幕
    • 会旋转的相机屏幕
    import 'dart:async';
    import 'dart:io';
    import 'package:flutter/material.dart';
    import 'package:camera/camera.dart';
    import 'package:flutter/services.dart';
    
    List<CameraDescription> cameras = [];
    
    Future<void> main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
      cameras = await availableCameras();
      runApp(MaterialApp(home: WelcomeScreen()));
    }
    
    class WelcomeScreen extends StatelessWidget {
      const WelcomeScreen({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Text('Welcome! Try rotating the screen, you won\'t be able to!'),
                SizedBox(height: 10),
                ElevatedButton(
                  onPressed: () => Navigator.of(context).pushReplacement(
                    MaterialPageRoute(builder: (_) => CameraApp()),
                  ),
                  child: Text('Press me to go to the camera'),
                ),
              ],
            ),
          ),
        );
      }
    }
    
    class CameraApp extends StatefulWidget {
      @override
      _CameraAppState createState() => _CameraAppState();
    }
    
    class _CameraAppState extends State<CameraApp> {
      CameraController? controller;
      bool takingPicture = false;
      XFile? selectedImage;
    
      @override
      void initState() {
        super.initState();
    
        // Remove the constraint when entering, this is ok
        // not to away since the app is in portrait mode by
        // default
        SystemChrome.setPreferredOrientations([
          DeviceOrientation.portraitUp,
          DeviceOrientation.landscapeLeft,
          DeviceOrientation.landscapeRight,
        ]);
        controller = CameraController(cameras[0], ResolutionPreset.max);
        controller!.initialize().then((_) {
          if (!mounted) {
            return;
          }
          setState(() {});
        });
      }
    
      @override
      void dispose() {
        controller?.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        if (!controller!.value.isInitialized) {
          return Container();
        }
        return MaterialApp(
          home: Stack(
            fit: StackFit.expand,
            children: [
              RotatedBox(
                quarterTurns: 1 - controller!.description.sensorOrientation ~/ 90,
                child: CameraPreview(controller!),
              ),
              CameraPreview(controller!),
              Align(
                alignment: Alignment.bottomCenter,
                child: ElevatedButton(
                  onPressed: () async {
                    // Restore the constraint before navigating away
                    // DO await here to avoid any other screen in
                    // landscape mode
                    await SystemChrome.setPreferredOrientations([
                      DeviceOrientation.portraitUp,
                    ]);
    
                    Navigator.of(context).pushReplacement(
                      MaterialPageRoute(builder: (_) => WelcomeScreen()),
                    );
                  },
                  child: Text('Press me to go Home'),
                ),
              ),
              Align(
                alignment: Alignment.bottomRight,
                child: FloatingActionButton(
                  onPressed: () async {
                    if (!takingPicture) {
                      takingPicture = true;
                      controller!.takePicture().then(
                        (value) {
                          selectedImage = value;
                          setState(() {});
                          takingPicture = false;
                        },
                      );
                    }
                  },
                ),
              ),
              Align(
                alignment: Alignment.bottomLeft,
                child: selectedImage != null
                    ? Container(
                        height: 100,
                        width: 200,
                        child: Image.file(
                          File(selectedImage!.path),
                        ),
                      )
                    : Container(),
              ),
            ],
          ),
        );
      }
    }
    

    【讨论】:

    • 但是如果我拍照,它仍然会以纵向模式显示图像(在左下角)
    • 这只有在设备上启用了自动旋转时才有效。但是,例如,即使设备上禁用了自动旋转功能,标准相机应用程序也能正常工作。
    猜你喜欢
    • 2014-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-28
    • 1970-01-01
    • 2022-11-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多