【问题标题】:AspectRatio problem with Flutter camera and image layerFlutter相机和图像层的AspectRatio问题
【发布时间】:2020-09-09 07:22:41
【问题描述】:

我的 Flutter 相机(插件“camera_camera”)和我放在它上面的图像有一个 AspectRatio 问题,透明层作为图层。

我将问题的屏幕截图发送给您。在屏幕截图中,您可以看到打开的相机,在它上方是我在它前面拍摄的照片。不幸的是,您可以在不同的地方看到它不匹配。

如何让相机显示与我之前从完全相同的位置拍摄的完全相同的比例?

如果这有帮助:我还录制了一个有关该问题的视频: https://danielederosa.de/downloads/flutter_issue.mp4

我的代码

@override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    if (!controller.value.isInitialized) {
      return Container(
          color: theme.colorScheme.onPrimary,
          child: Center(child: CircularProgressIndicator()));
    }

    return Scaffold(
      appBar: CupertinoNavigationBar(
        backgroundColor: theme.colorScheme.primary,
        border: Border.symmetric(
            vertical: BorderSide.none, horizontal: BorderSide.none),
        automaticallyImplyLeading: false,
        leading: IconButton(
          icon: Icon(
            Icons.chevron_left,
            size: 30,
            color: theme.colorScheme.onPrimary,
          ),
          onPressed: () => Navigator.pop(context),
        ),
        middle: Text("Memories",
            style: TextStyle(
                color: theme.colorScheme.onPrimary,
                fontSize: theme.textTheme.headline3.fontSize)),
      ),
      body: Container(
        child: Column(
          children: [
            Expanded(
              child: Camera(
                mode: CameraMode.normal,
                imageMask: lastPicture != null
                    ? new Positioned.fill(
                        child: new Opacity(
                          opacity: 0.3,
                          child: RotatedBox(
                            quarterTurns: 1,
                            child: new Image.file(
                              File(lastPicture),
                              fit: BoxFit.cover,
                            ),
                          ),
                        ),
                      )
                    : Container(),
                onFile: (File file) {
                  _workWithImage(file);
                },
              ),
            ),
          ],
        ),
      ),
    );
  }

我还尝试使用aspectRatio: 3/4 将Camera 小部件包装到AspectRatio 小部件中,因为我保存的图像保存在这个aspectRatio 中。但没有成功。

你有什么办法解决这个问题吗?

【问题讨论】:

标签: flutter dart


【解决方案1】:

我找到了解决方案并让它发挥作用。

示例代码

@override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);

    var deviceSize = MediaQuery.of(context).size;
    var sizeWidth = MediaQuery.of(context).size.width;
    final deviceRatio = deviceSize.width / deviceSize.height;
    var isPortrait = MediaQuery.of(context).orientation == Orientation.portrait;

    return Scaffold(
      backgroundColor: theme.colorScheme.primary,
      appBar: CupertinoNavigationBar(
        backgroundColor: theme.colorScheme.primary,
        border: Border.symmetric(
            vertical: BorderSide.none, horizontal: BorderSide.none),
        automaticallyImplyLeading: false,
        leading: IconButton(
          icon: Icon(
            Icons.chevron_left,
            size: 30,
            color: theme.colorScheme.onPrimary,
          ),
          onPressed: () => Navigator.pop(context),
        ),
        middle: Text(APP_NAME,
            style: TextStyle(
                color: theme.colorScheme.onPrimary,
                fontSize: theme.textTheme.headline3.fontSize)),
      ),
      body: NativeDeviceOrientationReader(
        useSensor: true,
        builder: (context) {
          NativeDeviceOrientation orientation =
              NativeDeviceOrientationReader.orientation(context);
          return Stack(children: [
            FutureBuilder<void>(
              future: _initializeControllerFuture,
              builder: (context, snapshot) {
                if (snapshot.connectionState == ConnectionState.done) {
                  // If the Future is complete, display the preview.
                  return MeasureSize(
                    onChange: (size) {
                      setState(() {
                        cameraSize = size;
                      });
                    },
                    child: Transform.scale(
                      scale: cameraController.value.aspectRatio / deviceRatio,
                      child: Center(
                        child: AspectRatio(
                          aspectRatio: cameraController.value.aspectRatio,
                          child: ClipRect(
                            child: OverflowBox(
                              alignment: Alignment.center,
                              child: FittedBox(
                                fit: BoxFit.fitWidth,
                                child: Container(
                                  width: sizeWidth,
                                  height: sizeWidth /
                                      cameraController.value.aspectRatio,
                                  child: CameraPreview(
                                      cameraController), // this is my CameraPreview
                                ),
                              ),
                            ),
                          ),
                        ),
                      ),
                    ),
                  );
                } else {
                  // Otherwise, display a loading indicator.
                  return Center(child: CircularProgressIndicator());
                }
              },
            ),
            helpMode == true
                ? Transform.scale(
                    scale: cameraController.value.aspectRatio / deviceRatio,
                    child: Center(
                      child: Opacity(
                        opacity: .3,
                        child: orientation ==
                                    NativeDeviceOrientation.landscapeLeft ||
                                orientation ==
                                    NativeDeviceOrientation.landscapeRight
                            ? RotatedBox(
                                quarterTurns: orientation ==
                                        NativeDeviceOrientation.landscapeLeft
                                    ? 1
                                    : 3,
                                child: Image.file(
                                  File(lastPicture),
                                  height: cameraSize.width,
                                  fit: BoxFit.contain,
                                ))
                            : Image.file(
                                File(lastPicture),
                                width: cameraSize.width,
                                height: cameraSize.height,
                                fit: BoxFit.contain,
                              ),
                      ),
                    ),
                  )
                : Container(),
          ]);
        },
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
      floatingActionButton: Container(
        transform: Matrix4.translationValues(0.0, -8.0, 0.0),
        child: FloatingActionButton(
          backgroundColor: theme.colorScheme.primary,

          child: Icon(
            Icons.camera_alt,
            color: theme.colorScheme.onPrimary,
          ),
          // Provide an onPressed callback.
          onPressed: () async {
            // Take the Picture in a try / catch block. If anything goes wrong,
            // catch the error.
            try {
              // Ensure that the camera is initialized.
              //await _initializeControllerFuture;

              // Construct the path where the image should be saved using the path
              // package.
              final path = join(
                // Store the picture in the temp directory.
                // Find the temp directory using the `path_provider` plugin.
                (await getTemporaryDirectory()).path,
                '${DateTime.now()}.png',
              );

              // Attempt to take a picture and log where it's been saved.
              await cameraController.takePicture(path);
              _workWithImage(File(path));
            } catch (e) {
              // If an error occurs, log the error to the console.
              print(e);
            }
          },
        ),
      ),
    );
  }
}

typedef void OnWidgetSizeChange(Size size);

class MeasureSize extends StatefulWidget {
  final Widget child;
  final OnWidgetSizeChange onChange;

  const MeasureSize({
    Key key,
    @required this.onChange,
    @required this.child,
  }) : super(key: key);

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

class _MeasureSizeState extends State<MeasureSize> {
  @override
  Widget build(BuildContext context) {
    SchedulerBinding.instance.addPostFrameCallback(postFrameCallback);
    return Container(
      key: widgetKey,
      child: widget.child,
    );
  }

  var widgetKey = GlobalKey();
  var oldSize;

  void postFrameCallback(_) {
    var context = widgetKey.currentContext;
    if (context == null) return;

    var newSize = context.size;
    if (oldSize == newSize) return;

    oldSize = newSize;
    widget.onChange(newSize);
  }
}

我创建了MeasureSize 类。通过这个类,我得到了一个子小部件的尺寸。在这种情况下,我需要相机的宽度和高度。 (Transform.scale) 在我得到这个之后,我只需要为图像叠加设置这个尺寸:

Image.file(
  File(lastPicture),
  width: cameraSize.width,
  height: cameraSize.height,
  fit: BoxFit.contain,
),

现在图像叠加层适合相机显示的内容。

【讨论】:

    猜你喜欢
    • 2020-02-09
    • 1970-01-01
    • 1970-01-01
    • 2021-10-06
    • 2018-10-25
    • 1970-01-01
    • 2016-07-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多