Fixing Stretched Camera Preview on Flutter Rotation

Experiencing a stretched or distorted camera preview when rotating your Flutter app, even when locked in portrait mode? This guide provides a practical solution to ensure your camera preview displays correctly, regardless of device orientation.

The Problem: Camera Preview Distortion on Rotation

You’ve integrated the camera package into your Flutter app and noticed that when the user rotates their device (e.g., from portrait to landscape), the camera preview stretches or breaks, even though your app is designed to only support portrait orientation. This happens because the camera tries to automatically adjust its orientation to match the device’s physical orientation.

The Solution: Lock Camera Capture Orientation

The key to resolving this issue is to explicitly lock the camera’s capture orientation to portrait mode. This prevents the camera from attempting to rotate with the device, ensuring a consistent preview appearance.

Step-by-Step Guide

  1. Initialize the Camera Controller: Begin by initializing your CameraController as usual.
  2. Lock Capture Orientation: After the controller is initialized, use the lockCaptureOrientation method to lock the camera to portrait mode.

Code Example


Future<void> initializeCamera() async {
  await controller?.dispose();
  controller = CameraController(
    _cameras,
    ResolutionPreset.max,
    enableAudio: false,
  );
  try {
      await controller!.initialize();
      // Lock to portrait orientation AFTER initializing the controller
      await controller!.lockCaptureOrientation(DeviceOrientation.portraitUp);
  } on CameraException catch (e) {
      // Handle camera initialization errors
      print('Error initializing camera: $e');
  }

  notifyListeners();
}

Explanation:

  • controller?.dispose();: Disposes of any existing camera controller to avoid conflicts.
  • CameraController(...): Creates a new CameraController instance.
  • await controller!.initialize();: Initializes the camera controller. This is a crucial step before locking the orientation.
  • await controller!.lockCaptureOrientation(DeviceOrientation.portraitUp);: Locks the camera capture orientation to portrait up, preventing rotation.
  • try...catch: Handle any camera initialization errors
  • notifyListeners();: Updates the UI after successful initialization.

Possible Errors and Solutions

Sometimes you can get CameraException when controller.initialize(). Here is some possible errors and the fix:

Error Code Error Description Solution
cameraAccessDenied The app doesn’t have permission to use the camera. Request camera permissions from the user before initializing the camera. Use a package like permission_handler.
cameraNotFound No camera is available on the device. Check if the device has a camera. Also, ensure no other app is using the camera simultaneously.
cameraNotInitialized The camera controller was not properly initialized. Make sure you call await controller!.initialize(); before attempting to use the camera.
resolutionNotSupported The selected resolution is not supported by the camera. Try a different ResolutionPreset.

Complete Working Example


import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class CameraPreviewWidget extends StatefulWidget {
  const CameraPreviewWidget({super.key});

  @override
  State createState() => _CameraPreviewWidgetState();
}

class _CameraPreviewWidgetState extends State {
  CameraController? controller;
  List? cameras;
  bool _isCameraInitialized = false;

  @override
  void initState() {
    super.initState();
    _initializeCamera();
  }

  Future _initializeCamera() async {
    cameras = await availableCameras();
    if (cameras == null || cameras!.isEmpty) {
      print('No cameras available');
      return;
    }

    controller = CameraController(cameras![0], ResolutionPreset.medium);

    try {
      await controller!.initialize();
      await controller!.lockCaptureOrientation(DeviceOrientation.portraitUp);
      setState(() {
        _isCameraInitialized = true;
      });
    } on CameraException catch (e) {
      print('Camera initialization error: $e');
    }
  }

  @override
  void dispose() {
    controller?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    if (!_isCameraInitialized) {
      return const Center(child: CircularProgressIndicator());
    }

    return AspectRatio(
      aspectRatio: 1 / controller!.value.aspectRatio,
      child: CameraPreview(controller!),
    );
  }
}

Important: Ensure you have added the camera package to your pubspec.yaml file and have requested the necessary camera permissions from the user. You may need to use a package like permission_handler for handling permissions on different platforms.

Conclusion

By locking the camera capture orientation to portrait mode, you can effectively prevent the stretched or distorted camera preview issue in your Flutter apps. Remember to initialize the camera controller before locking the orientation. This simple fix ensures a consistent and user-friendly camera experience, even when the device is rotated.