.NET MAUI中如何实现前置摄像头预览及按钮触发拍照功能?
在.NET MAUI中实现前置摄像头预览+按钮拍照的方案
目前.NET MAUI Community Toolkit确实还没有提供CameraView控件,你可以通过以下两种方式实现需求:
方案一:使用第三方库Camera.MAUI
这是最快捷的实现方式,该库专为MAUI打造,支持摄像头预览、拍照、切换前后置等核心功能。
- 安装NuGet包:
Camera.MAUI - 在
MauiProgram.cs中初始化库:
builder.UseMauiApp<App>().UseCamera();
- 在XAML页面中添加相机预览控件和拍照按钮:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:camera="clr-namespace:Camera.MAUI;assembly=Camera.MAUI" x:Class="YourNamespace.CameraPage"> <Grid> <!-- 前置摄像头预览控件 --> <camera:CameraView x:Name="cameraView" CameraOptions="Front" HorizontalOptions="Fill" VerticalOptions="Fill"/> <!-- 拍照触发按钮 --> <Button Text="拍照" VerticalOptions="End" HorizontalOptions="Center" Margin="0,0,0,20" Clicked="OnTakePhotoClicked"/> </Grid> </ContentPage>
- 在后台代码实现拍照逻辑:
private async void OnTakePhotoClicked(object sender, EventArgs e) { if (cameraView.IsCameraAvailable) { var photo = await cameraView.CapturePhotoAsync(); if (photo != null) { // 处理拍摄的照片,比如保存到本地或显示在Image控件中 var imageSource = ImageSource.FromStream(() => photo.AsStream()); // photoImage.Source = imageSource; // 假设页面有一个名为photoImage的Image控件 } } }
方案二:自定义平台视图(Handler)实现原生预览
如果不想依赖第三方库,可以通过MAUI的Handler机制,针对各平台编写原生相机逻辑,封装成可复用的自定义控件。
核心步骤:
- 在共享项目中定义
CameraPreview自定义控件 - 为Android、iOS、Windows分别编写Handler,实现原生前置摄像头预览和拍照逻辑
- 在页面中使用自定义控件+按钮完成交互
简化版示例代码:
- 共享项目自定义控件:
public class CameraPreview : View { // 绑定拍照命令 public static readonly BindableProperty TakePhotoCommandProperty = BindableProperty.Create(nameof(TakePhotoCommand), typeof(ICommand), typeof(CameraPreview)); public ICommand TakePhotoCommand { get => (ICommand)GetValue(TakePhotoCommandProperty); set => SetValue(TakePhotoCommandProperty, value); } // 照片拍摄完成事件 public event EventHandler<Stream> PhotoCaptured; }
- Android平台Handler关键实现:
[assembly: ExportHandler(typeof(CameraPreview), typeof(CameraPreviewHandler))] namespace YourNamespace.Platforms.Android { public class CameraPreviewHandler : ViewHandler<CameraPreview, Android.Views.View> { private CameraXPreviewView _previewView; private ImageCapture _imageCapture; protected override Android.Views.View CreatePlatformView() { _previewView = new CameraXPreviewView(Context); // 配置CameraX前置摄像头 var cameraProviderFuture = ProcessCameraProvider.GetInstance(Context); cameraProviderFuture.AddListener(() => { var cameraProvider = cameraProviderFuture.Get(); var preview = new Preview.Builder().Build(); var cameraSelector = new CameraSelector.Builder() .RequireLensFacing(LensFacing.Front) .Build(); _imageCapture = new ImageCapture.Builder().Build(); preview.SetSurfaceProvider(_previewView.SurfaceProvider); cameraProvider.BindToLifecycle((Activity)Context, cameraSelector, preview, _imageCapture); }, Context.MainExecutor); return _previewView; } protected override void ConnectHandler(Android.Views.View platformView) { base.ConnectHandler(platformView); VirtualView.TakePhotoCommand = new Command(async () => { var outputFile = new File(Context.CacheDir, $"photo_{Guid.NewGuid()}.jpg"); var outputOptions = new ImageCapture.OutputFileOptions.Builder(outputFile).Build(); await _imageCapture.TakePictureAsync(outputOptions, Context.MainExecutor, new ImageCaptureCallback(VirtualView)); }); } private class ImageCaptureCallback : ImageCapture.OnImageSavedCallback { private readonly CameraPreview _virtualView; public ImageCaptureCallback(CameraPreview virtualView) => _virtualView = virtualView; public void OnImageSaved(ImageCapture.OutputFileResults outputFileResults) { using var stream = new FileStream(outputFileResults.SavedUri.Path, FileMode.Open); _virtualView.PhotoCaptured?.Invoke(null, stream); } public void OnError(int imageCaptureError, string message, Exception exception) { // 处理拍照错误 } } } }
- XAML页面使用自定义控件:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:YourNamespace" x:Class="YourNamespace.CameraPage"> <Grid> <local:CameraPreview x:Name="cameraPreview"/> <Button Text="拍照" VerticalOptions="End" HorizontalOptions="Center" Margin="0,0,0,20" Command="{Binding Source={x:Reference cameraPreview}, Path=TakePhotoCommand}"/> </Grid> </ContentPage>
注:iOS和Windows平台需编写对应Handler,分别使用AVFoundation(iOS)、MediaCapture(Windows)API实现前置摄像头预览和拍照逻辑,核心思路与Android一致。
内容的提问来源于stack exchange,提问作者jerome
相关产品推荐
相关产品推荐

