在Flutter中拍摄横向和纵向的相机照片,并禁用旋转。

5
我希望构建一个屏幕,可以拍摄横向和纵向的照片。我的应用程序只能在纵向模式下运行,通过在主要代码中调用以下代码实现:

await 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 上的普通移动应用程序也可以实现这一点。

1个回答

0
我会在进入屏幕时移除约束条件,并在重新进入时重新应用它。
以下是从您的代码中改编的示例,其中包含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(),
          ),
        ],
      ),
    );
  }
}

但是如果我拍照,它仍然会在竖屏模式下显示图像(在左下角)。 - targiasld
2
只有在设备上启用了自动旋转功能,此方法才能正常工作。但是标准相机应用程序例如,在设备上禁用自动旋转功能时仍然可以使用。 - targiasld
@O.T,你有这个问题的解决方案吗? 我正在尝试制作一个类似于标准相机应用程序的应用程序,即使系统的自动旋转被锁定,也可以自动旋转。 - Irfandi D. Vendy
@IrfandiD.Vendy 我使用了 https://pub.dev/packages/native_device_orientation 来检查设备方向,并根据其更改相机控制器上的捕获方向,在拍照后进行操作。 - targiasld

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接