简体   繁体   English

相机预览不匹配设备 | flutter

[英]Camera preview not matching device | flutter

My camera preview is distorted.我的相机预览失真。 It appears far too zoomed in, and also stretched.它看起来太放大了,而且也被拉伸了。

What am I doing wrong?我究竟做错了什么? How can I fix?我该如何解决?

 final size = MediaQuery.of(context).size;
    final deviceRatio = size.width / size.height;
    return Stack(children: <Widget>[
      Center(
        child: Transform.scale(
          scale: controller.value.aspectRatio / deviceRatio,
          child: new AspectRatio(
            aspectRatio: controller.value.aspectRatio,
            child: new CameraPreview(controller),
          ),
        ),
      ),
    ]);
  }

Note: Should work for iOS and Android.注意:应该适用于 iOS 和 Android。

I am using camera package: camera: ^0.7.0+2我正在使用相机 package:相机:^0.7.0+2

Here full page这里整页

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

class Camera extends StatefulWidget {
  Function setData;
  Camera({Key key, this.setData}) : super(key: key);

  @override
  _CameraScreenState createState() => _CameraScreenState();
}

class _CameraScreenState extends State<Camera> {
  CameraController controller;
  List cameras;
  int selectedCameraIndex;
  String imgPath;
  var image;

  Future _openGallery() async {
    image = await controller.takePicture();
    if (widget.setData != null) {
      widget.setData(File(image.path));
    }
  }

  @override
  void initState() {
    super.initState();
    availableCameras().then((availableCameras) {
      cameras = availableCameras;

      if (cameras.length > 0) {
        setState(() {
          selectedCameraIndex = 0;
        });
        _initCameraController(cameras[selectedCameraIndex]).then((void v) {});
      } else {
        print('No camera available');
      }
    }).catchError((err) {
      print('Error :${err.code}Error message : ${err.message}');
    });
  }

  Future _initCameraController(CameraDescription cameraDescription) async {
    if (controller != null) {
      await controller.dispose();
    }
    controller = CameraController(cameraDescription, ResolutionPreset.high);

    controller.addListener(() {
      if (mounted) {
        setState(() {});
      }

      if (controller.value.hasError) {
        print('Camera error ${controller.value.errorDescription}');
      }
    });

    try {
      await controller.initialize();
    } on CameraException catch (e) {}
    if (mounted) {
      setState(() {});
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        child: SafeArea(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[
              Expanded(
                flex: 1,
                child: _cameraPreviewWidget(),
              ),
              Align(
                alignment: Alignment.bottomCenter,
                child: Container(
                  height: 120,
                  width: double.infinity,
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.start,
                    children: <Widget>[_cameraControlWidget(context), Spacer()],
                  ),
                ),
              )
            ],
          ),
        ),
      ),
    );
  }

  Widget _cameraPreviewWidget() {
    if (controller == null || !controller.value.isInitialized) {
      return const Text(
        'Loading',
        style: TextStyle(
          color: Colors.white,
          fontSize: 20.0,
          fontWeight: FontWeight.w900,
        ),
      );
    }

    final size = MediaQuery.of(context).size;
    final deviceRatio = size.width / size.height;
    return Stack(children: <Widget>[
      Center(
        child: Transform.scale(
          scale: controller.value.aspectRatio / deviceRatio,
          child: new AspectRatio(
            aspectRatio: controller.value.aspectRatio,
            child: new CameraPreview(controller),
          ),
        ),
      ),
    ]);
  }

  Widget _cameraControlWidget(context) {
    return Expanded(
      child: Align(
        alignment: Alignment.center,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          mainAxisSize: MainAxisSize.max,
          children: <Widget>[
            FloatingActionButton(
              child: Icon(
                Icons.camera,
                color: Colors.black,
              ),
              backgroundColor: Colors.white,
              onPressed: () {
                _openGallery();
                Navigator.pop(context);
              },
            )
          ],
        ),
      ),
    );
  }
}

在此处输入图像描述

Edit based on answer:根据答案编辑:

final size = MediaQuery.of(context).size;
    final deviceRatio = size.width / size.height;
    return Stack(children: <Widget>[
      Center(
        child: Transform.scale(
          scale: 16 / 9,
          child: Center(
            child: AspectRatio(
              aspectRatio: 1,
              child: Camera(),
            ),
          ),
        ),
      ),
    ]);
  }

Had the same problem using camerawesome some times ago.前段时间使用camerawesome时遇到了同样的问题。

Had to use Transform and an Aspect Ratio:必须使用变换和纵横比:

                   Transform.scale(
                      scale: 16 / 9,
                      child: Center(
                        child: AspectRatio(
                          aspectRatio: 1,
                          child: Camera(),
                        ),
                      ),
                    ),

Use Matrix4.diagonal3Values for scaling, as we can then control the X, Y, Z axis.使用 Matrix4.diagonal3Values 进行缩放,因为我们可以控制 X、Y、Z 轴。 X is the horizontal, Y is the vertical and Z is for the ones that want to go into other dimensions. X 是水平的,Y 是垂直的,Z 是那些想要 go 到其他维度的。

final size = MediaQuery.of(context).size;
final deviceRatio = size.width / size.height;
final xScale = cameraController.value.aspectRatio / deviceRatio;
// Modify the yScale if you are in Landscape
final yScale = 1;
return Container(
  child: AspectRatio(
        aspectRatio: deviceRatio,
        child: Transform(
          alignment: Alignment.center,
          transform: Matrix4.diagonal3Values(xScale, yScale, 1),
          child: CameraPreview(cameraController),
        ),
    ),
);

If you are working with a camera that rotates and supports Landscape, you will most likely need to scale up the Y axis, and skip the X.如果您使用的是旋转并支持风景的相机,您很可能需要放大 Y 轴,并跳过 X。

The Lightsnap app is locked in Portrait so we don't need to re-scale the camera preview when the phone rotates. Lightsnap 应用程序锁定在人像中,因此我们不需要在手机旋转时重新缩放相机预览。 Just a note that you may need to do this if you are supporting landscape.请注意,如果您支持景观,则可能需要这样做。

Thanks to Lightsnap(More Details here) 感谢 Lightsnap(此处有更多详细信息)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM