A Camera View control and a Barcode Endode/Decode control (based on ZXing.Net) for .NET MAUI applications.
A ContetView control for camera management with the next properties:
| Android | iOS/Mac | Windows | |
|---|---|---|---|
| Preview | ✅ | ✅ | ✅ |
| Mirror preview | ✅ | ✅ | ✅ |
| Flash | ✅ | ✅ | ✅ |
| Torch | ✅ | ✅ | ✅ |
| Zoom | ✅ | ✅ | ✅ |
| Take snapshot | ✅ | ✅ | ✅ |
| Save snapshot | ✅ | ✅ | ✅ |
| Barcode detection/decode | ✅ | ✅ | ✅ |
| Video/audio recording | ✅ | ✅ | ✅ |
| Take Photo | ✅ | ✅ | ✅ |
Download and Install Camera.MAUI NuGet package on your application.
Download and Install Camera.MAUI.ZXing NuGet package on your application (if you want Barcode detection/decode with ZXing).
Initialize the plugin in your
MauiProgram.cs:// Add the using to the topusingCamera.MAUI;publicstaticMauiAppCreateMauiApp(){varbuilder=MauiApp.CreateBuilder();builder.UseMauiApp<App>().UseMauiCameraView();// Add the use of the pluggingreturnbuilder.Build();}
Add camera/microphone permissions to your application:
In your AndroidManifest.xml file (Platforms\Android) add the following permission:
<uses-permissionandroid:name="android.permission.CAMERA" />
<uses-permissionandroid:name="android.permission.RECORD_AUDIO" />
<uses-permissionandroid:name="android.permission.RECORD_VIDEO" />
In your info.plist file (Platforms\iOS / Platforms\MacCatalyst) add the following permission:
<key>NSCameraUsageDescription</key>
<string>This app uses camera for...</string>
<key>NSMicrophoneUsageDescription</key>
<string>This app needs access to the microphone for record videos</string>Make sure that you enter a clear and valid reason for your app to access the camera. This description will be shown to the user.
In your Package.appxmanifest file (Platforms\Windows) go to Capabilities and mark Web Camera and Microphone.
For more information on permissions, see the Microsoft Docs.
In XAML, make sure to add the right XML namespace:
xmlns:cv="clr-namespace:Camera.MAUI;assembly=Camera.MAUI"
Use the control:
<cv:CameraViewx:Name="cameraView"WidthRequest="300"HeightRequest="200"/>Configure the events:
cameraView.CamerasLoaded+=CameraView_CamerasLoaded;cameraView.BarcodeDetected+=CameraView_BarcodeDetected;Configure the camera and microphone to use:
privatevoidCameraView_CamerasLoaded(objectsender,EventArgse){if(cameraView.NumCamerasDetected>0){if(cameraView.NumMicrophonesDetected>0)cameraView.Microphone=cameraView.Microphones.First();cameraView.Camera=cameraView.Cameras.First();MainThread.BeginInvokeOnMainThread(async()=>{if(awaitcameraView.StartCameraAsync()==CameraResult.Success){controlButton.Text="Stop";playing=true;}});}}CameraInfo type (Camera Property): CameraInfo has the next properties:
publicstringNamepublicstringDeviceId
public CameraPosition Position
publicboolHasFlashUnitpublicfloatMinZoomFactorpublicfloatMaxZoomFactorpublicfloatHorizontalViewAnglepublicfloatVerticalViewAnglepublicList<Size>AvailableResolutionsStart camera playback:
if(awaitcameraView.StartCameraAsync(newSize(1280,720))==CameraResult.Success){playing=true;}Stop camera playback:
if(awaitcameraView.StopCameraAsync()==CameraResult.Success){playing=false;}Set Flash mode
cameraView.FlashMode=FlashMode.Auto;Toggle Torch
cameraView.TorchEnabled=!cameraView.TorchEnabled;Set mirrored mode
cameraView.MirroredImage=true;Set zoom factor
if(cameraView.MaxZoomFactor>=2.5f)cameraView.ZoomFactor=2.5f;Get a snapshot from the playback
ImageSourceimageSource=cameraView.GetSnapShot(ImageFormat.PNG);boolresult=cameraView.SaveSnapShot(ImageFormat.PNG,filePath);Record a video:
varresult=awaitcameraView.StartRecordingAsync(Path.Combine(FileSystem.Current.CacheDirectory,"Video.mp4"),newSize(1920,1080));
....
result=awaitcameraView.StopRecordingAsync();Take a photo
varstream=awaitcameraView.TakePhotoAsync();if(stream!=null){varresult=ImageSource.FromStream(()=>stream);snapPreview.Source=result;}Use Control with MVVM: The control has several binding properties for take an snapshot:
/// Binding property for use this control in MVVM.publicCameraViewSelf/// Sets how often the SnapShot property is updated in seconds./// Default 0: no snapshots are taken/// WARNING! A low frequency directly impacts over control performance and memory usage (with AutoSnapShotAsImageSource = true)/// </summary>publicfloatAutoSnapShotSeconds/// Sets the snaphost image format
public ImageFormat AutoSnapShotFormat
/// Refreshes according to the frequency set in the AutoSnapShotSeconds property (if AutoSnapShotAsImageSource is set to true) or when GetSnapShot is called or TakeAutoSnapShot is set to truepublicImageSourceSnapShot/// Refreshes according to the frequency set in the AutoSnapShotSeconds property or when GetSnapShot is called./// WARNING. Each time a snapshot is made, the previous stream is disposed.
public Stream SnapShotStream
/// Change from false to true refresh SnapShot propertypublicboolTakeAutoSnapShot/// If true SnapShot property is refreshed according to the frequency set in the AutoSnapShotSeconds propertypublicboolAutoSnapShotAsImageSource/// Starts/Stops the Preview if camera property has been setpublicboolAutoStartPreview{get{return(bool)GetValue(AutoStartPreviewProperty);}set{SetValue(AutoStartPreviewProperty,value);}}/// Full path to file where record video will be recorded.publicstringAutoRecordingFile{get{return(string)GetValue(AutoRecordingFileProperty);}set{SetValue(AutoRecordingFileProperty,value);}}/// Starts/Stops record video to AutoRecordingFile if camera and microphone properties have been setpublicboolAutoStartRecording{get{return(bool)GetValue(AutoStartRecordingProperty);}set{SetValue(AutoStartRecordingProperty,value);}}<cv:CameraViewx:Name="cameraView"WidthRequest="300"HeightRequest="200"BarCodeOptions="{Binding BarCodeOptions}"BarCodeResults="{Binding BarCodeResults, Mode=OneWayToSource}"Cameras="{Binding Cameras, Mode=OneWayToSource}"Camera="{Binding Camera}"AutoStartPreview="{Binding AutoStartPreview}"NumCamerasDetected="{Binding NumCameras, Mode=OneWayToSource}"AutoSnapShotAsImageSource="True"AutoSnapShotFormat="PNG"TakeAutoSnapShot="{Binding TakeSnapshot}"AutoSnapShotSeconds="{Binding SnapshotSeconds}"Microphones="{Binding Microphones, Mode=OneWayToSource}"Microphone="{Binding Microphone}"NumMicrophonesDetected="{Binding NumMicrophones, Mode=OneWayToSource}"AutoRecordingFile="{Binding RecordingFile}"AutoStartRecording="{Binding AutoStartRecording}"/>You have a complete example of MVVM in MVVM Example
For barcodes detection, you must set the Camera Control BarCodeDecoder property. Enable and Handle barcodes detection with Camera.MAUI.ZXing:
usingCamera.MAUI.ZXing;cameraView.BarcodeDetected+=CameraView_BarcodeDetected;cameraView.BarCodeDecoder=newZXingBarcodeDecoder();cameraView.BarCodeOptions=newBarcodeDecodeOptions{AutoRotate=true,PossibleFormats={BarcodeFormat.QR_CODE},ReadMultipleCodes=false,TryHarder=true,TryInverted=true};cameraView.BarCodeDetectionFrameRate=10;cameraView.BarCodeDetectionMaxThreads=5;cameraView.ControlBarcodeResultDuplicate=true;cameraView.BarCodeDetectionEnabled=true;privatevoidCameraView_BarcodeDetected(objectsender,ZXingHelper.BarcodeEventArgsargs){Debug.WriteLine("BarcodeText="+args.Result[0].Text);}Use the event or the bindable property BarCodeResults
/// Event launched every time a code is detected in the image if "BarCodeDetectionEnabled" is set to true.publiceventBarcodeResultHandler BarcodeDetected;/// It refresh each time a barcode is detected if BarCodeDetectionEnabled porperty is truepublicResult[]BarCodeResultsA ContentView control for generate codebars images.
In XAML, make sure to add the right XML namespace:
xmlns:cv="clr-namespace:Camera.MAUI;assembly=Camera.MAUI"
Use the control and its bindable properties:
<cv:BarcodeImagex:Name="barcodeImage"Aspect="AspectFit"WidthRequest="400"HeightRequest="400"BarcodeWidth="200"BarcodeHeight="200"BarcodeMargin="5"BarcodeBackground="White"BarcodeForeground="Blue"BarcodeFormat="QR_CODE" />Set the BarcodeEncoder property to enable de image generator (example with Camera.MAUI.ZXing):
barcodeImage.BarcodeEncoder=newZXingBarcodeEncoder();Set the barcode property to generate the image:
barcodeImage.Barcode="https://github.com/hjam40/Camera.MAUI";