如何设置Flutter CameraPreview尺寸“全屏”

问题描述 投票:0回答:10

我使用CameraPreview来测量物体的高度,但问题是我无法全屏设置cameraPreview高度..

我尝试过定位小部件,它填满了屏幕,但图像被拉伸了。 我尝试过Transform Widget,但是高度没有填满全屏,空白即将到来。图像没有拉伸。

我的代码:

final size = MediaQuery.of(context).size;
final deviceRatio = size.width / size.height;

return Stack(
            children: <Widget>[
              Transform.scale(
                scale: controller.value.aspectRatio/deviceRatio,
                child: new AspectRatio(
                  aspectRatio: controller.value.aspectRatio,
                  child: new CameraPreview(controller),
                ),
              ),);

请帮助我调整 CameraPreview“全屏”而不进行图像拉伸..

android flutter flutter-layout
10个回答
36
投票
自 0.7.0 以来,

CameraValue.aspectRatio 返回宽度/高度而不是高度/宽度,并且 CameraPreview 现在处理 AspectRatio 本身,因此我认为工作代码片段如下: /// only work inside WidgetsApp or MaterialApp, which introduces a MediaQuery final scale = 1 / (controller.value.aspectRatio * MediaQuery.of(context).size.aspectRatio); return Transform.scale( scale: scale, alignment: Alignment.topCenter, child: CameraPreview(controller), );

更新:

通过变换缩放后,在

TransitionRoute

中使用时,预览可能会超出屏幕尺寸限制。 (当托管在 CupertinoPageRoute 中时,拖动手势将清楚地显示这一点)。 所以我认为剪辑预览以使其完全匹配屏幕尺寸是个好主意。

final mediaSize = MediaQuery.of(context).size; final scale = 1 / (controller.value.aspectRatio * mediaSize.aspectRatio); return ClipRect( clipper: _MediaSizeClipper(mediaSize), child: Transform.scale( scale: scale, alignment: Alignment.topCenter, child: CameraPreview(controller), ), ); class _MediaSizeClipper extends CustomClipper<Rect> { final Size mediaSize; const _MediaSizeClipper(this.mediaSize); @override Rect getClip(Size size) { return Rect.fromLTWH(0, 0, mediaSize.width, mediaSize.height); } @override bool shouldReclip(CustomClipper<Rect> oldClipper) { return true; } }



7
投票
CameraPreview

FittedBox
包裹在
BoxFit.cover
中,并确保父容器等于您要填充的空间。
@override
Widget build(BuildContext context) {
  final size = MediaQuery.of(context).size;

  return Scaffold(
      body: cameraController == null
          ? const Text("Loading Camera...")
          : Container(
              width: size.width,
              height: size.height,
              child: FittedBox(
                fit: BoxFit.cover,
                child: Container(
                    width: 100, // the actual width is not important here
                    child: CameraPreview(cameraController!)),
              )));
}



6
投票
通过将 Center 小部件包装在 Transform 小部件中解决了问题

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), ), ),),);



4
投票

LayoutBuilder( builder: (context, constraints) { return SizedBox( width: constraints.maxWidth, height: constraints.maxHeight, child: CameraPreview(controller), ); }, ),

它会像魅力一样发挥作用


3
投票

var isPortrait = MediaQuery.of(context).orientation == Orientation.portrait; Size mediaSize = MediaQuery.of(context).size; return SizedBox( width: mediaSize.width, height: mediaSize.height, child: FittedBox( fit: BoxFit.cover, child: SizedBox( width: isPortrait ? _controller!.value.previewSize!.height : _controller!.value.previewSize!.width, height: isPortrait ? _controller!.value.previewSize!.width : _controller!.value.previewSize!.height, child: CameraPreview(_controller!)), ), );



1
投票


1
投票

我有两个状态小部件字段:

cameraControllerKey

,用于引用保存 CameraPreview 的容器。

cameraPreviewScale
用于存储原始cameraPreview的尺寸。
在我的构建方法中,我首先让 CameraView 构建其 UI 并将比例设置为 1,这意味着我只是让它在出现时自行绘制(所以不是全屏......但是)。另请注意,我将 

key

设置为我的 GlobalKey

cameraControllerKey
。 在
addPostFrameCallback
方法中,我根据保存 CameraPreview 的容器视图大小和实际屏幕大小来计算比例。希望对你有帮助,快乐飘飘。
///field in widget state
var cameraControllerKey = GlobalKey();
double? cameraPreviewScale;


/// In build method
if(cameraPreviewScale==null){
  WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
    final screenSize = MediaQuery.of(context).size;
    final previewSize = cameraControllerKey.currentContext!.size!;
    setState(() {
      cameraPreviewScale = screenSize.width / previewSize.width;    
    });
  });
}

return Scaffold(
key: _scaffoldKey,
body: 
  Stack(
    fit: StackFit.loose,
    children: [
      Center(
        child: Container(
            key: cameraControllerKey,
            child: Transform.scale(
                alignment: Alignment.center,
                scale: cameraPreviewScale ?? 1,
                child: CameraPreview(cameraController!))),
      ),
    ],
  )
);



0
投票
FittedBox

SizedBox
的组合,您可以固定相机尺寸以填充整个屏幕,并保持预览准确(不拉伸)。
使用以下代码片段:

FittedBox( fit: BoxFit.fitWidth, // This ensures the width is fully covered without stretching. child: SizedBox( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height, child: CameraPreview(_controller), ), ),

让我们了解一下小部件的工作原理,以阐明其工作原理:

    FittedBox
  1. BoxFit.fitWidth
    确保 CameraPreview 的宽度与屏幕的宽度相匹配。通过执行
    BoxFit.fitWidth
    ,我们确保宽度被填充而不拉伸高度。
  2. SizedBox
  3. :宽度设置为与屏幕宽度匹配,高度设置为与屏幕高度匹配。这可确保 CameraPreview 覆盖整个屏幕。
    
        

-1
投票
https://flutter.dev/docs/cookbook/plugins/picture-using-camera

的演示 并且我没有自定义 CameraPreview 的 AspectRatio(实际上我做了,但它不起作用)。

我解决的方法很简单。

return Stack( children: [ Container( width: double.infinity, height: double.infinity, child: CameraPreview(_cameraController)) ], );

我正在使用 Container 小部件的属性宽度和高度来使 CameraPreview 拉伸为全屏。


-2
投票
此代码适用于 Flutter 2.8 及以上版本

return Stack( children: [ Positioned( top: 0, bottom: 0, child: CameraPreview(_cameraController!), ), ], );

© www.soinside.com 2019 - 2024. All rights reserved.