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
- Initialize the Camera Controller: Begin by initializing your
CameraController
as usual. - 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 newCameraController
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 errorsnotifyListeners();
: 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.