Ahmad Sattout
Ahmad Sattout

Reputation: 2486

Changing the CameraPreview Aspect Ratio (Flutter)

I have an app where I have a Scaffold with an AppBar and a bottom Ads Banner.

In between, there is the CameraPreview from the camera plugin in Flutter.

As the CameraPreview is made to take the aspect ratio of the device/camera, the CameraPreview doesn't take the entire available space, leaving extra space on most devices.

I tried to crop the CameraPreview to show only whatever fits in the available space. It worked, but now the preview is stretched out

LayoutBuilder(
    builder: (context, constraints) {
        final cameraController = controller.cameraController!;
        if(cameraController.value.previewSize != null) {
            return ClipRect(
                child: OverflowBox(
                alignment: Alignment.center,
                    child: FittedBox(
                    fit: BoxFit.fitWidth,
                    child: SizedBox(
                        width: constraints.maxWidth,
                        height: constraints.maxWidth,
                        child: AspectRatio(
                            aspectRatio: cameraController.value.aspectRatio,
                            child: CameraPreview(cameraController),
                            ),
                         ),
                     ),
                 ),
            );
        } else {
            return const SizedBox.shrink();
        }
    },
)

I tried other solutions like Transform.scale, but that only zooms into the preview, it doesn't change the ratio or the stretching.

Looking solutions in the package itself doesn't help either, most similar issues are stalling or already closed for stalling.

What am I supposed to do here? Am I supposed to manually clip the preview's value?

Upvotes: 2

Views: 2697

Answers (1)

Jai Techie
Jai Techie

Reputation: 1957

check this below code,

Use get screen size by MediaQuery & calculate scale for aspect ratio widget and add CameraPreview() to it like below

    // get screen size
    final size = MediaQuery.of(context).size;

    // calculate scale for aspect ratio widget
    var scale = cameraController.value.aspectRatio / size.aspectRatio;

    // check if adjustments are needed...
    if (cameraController.value.aspectRatio < size.aspectRatio) {
      scale = 1 / scale;
    }

return Transform.scale(
      scale: scale,
      child: Center(
        child: AspectRatio(
          aspectRatio: cameraController.value.aspectRatio,
          child: CameraPreview(cameraController),
        ),
      ),
    );

Complete code

 @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () {
        if (controller != null && controller.value.isRecordingVideo) {
          //stop video
        }
      },
      child: Scaffold(
        resizeToAvoidBottomInset: false,
        key: _scaffoldKey,
        body: Container(
          child: Stack(
            children: [
              Positioned(
                child: Container(
                  alignment: Alignment.center,
                  child: cameraScreen(),
                ),
              ),
              Positioned(
                child: Container(
                  alignment: Alignment.bottomCenter,
                  child: Container(
                    height: MediaQuery.of(context).size.height * .1,
                    color: Colors.black54,
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: [
                        //can add Controls
                      ],
                    ),
                  ),
                ),
              )
            ],
          ),
        ),
      ),
    );
  }

  Widget cameraScreen() {
    final CameraController cameraController = controller;
    if (cameraController == null || !cameraController.value.isInitialized) {
      return Container(
        width: MediaQuery.of(context).size.width,
        height: MediaQuery.of(context).size.height,
        color: Colors.black,
        child: Center(
          child: Text(
            "Loading Camera...",
            style: CameraTextStyle.cameraUtilLoadingStyle(),
          ),
        ),
      );
    } else {
      return cameraWidget(context, cameraController);
    }
  }

  Widget cameraWidget(context, cameraController) {
    // get screen size
    final size = MediaQuery.of(context).size;

    // calculate scale for aspect ratio widget
    var scale = cameraController.value.aspectRatio / size.aspectRatio;

    // check if adjustments are needed...
    if (cameraController.value.aspectRatio < size.aspectRatio) {
      scale = 1 / scale;
    }

    return Transform.scale(
      scale: scale,
      child: Center(
        child: AspectRatio(
          aspectRatio: cameraController.value.aspectRatio,
          child: CameraPreview(cameraController),
        ),
      ),
    );
  }

  Widget cameraSwitch() {
    final CameraController cameraController = controller;
    return Container(
      child: InkWell(
        onTap: () {
          if (cameraController != null &&
              cameraController.value.isInitialized &&
              !cameraController.value.isRecordingVideo) {
            if (cameras.isNotEmpty) {
              if (selectedCamera == cameras[0]) {
                selectedCamera = cameras[1];
                onNewCameraSelected(selectedCamera);
              } else {
                selectedCamera = cameras[0];
                onNewCameraSelected(selectedCamera);
              }
            }
          }
          setState(() {});
        },
        child: Icon(
          Icons.switch_camera,
          size: 30,
          color: Colors.white,
        ),
      ),
    );
  }

Upvotes: 1

Related Questions