Maui Blazor iOS端多选照片以及显示本地照片
安卓端参考之前这篇文章:https://www.cnblogs.com/wecareu/p/17855415.html
iOS端,目前Maui提供的原生接口是MediaPicker 应该对应调用的是iOS原生的UIIMagePicker, 效果也不错,但是一次只能选择单张照片
在ios14以后,苹果推出了新的PHPickerViewController,支持多选照片,UI以弹窗的形式出现,效果十分不错。
1. 在Platform-iOS里新建IOSPhotoPIckerService.cs, 由于PHPickerViewController是新添加的,所以别忘记引进using PhotosUI;添加如下代码:
[assembly: Dependency(typeof(IOSPhotoPickerService))] namespace AndroidPhotoPicker.Platforms.iOS { public class IOSPhotoPickerService : IPhotoPickerService { class PPD : PHPickerViewControllerDelegate { public Action<PHPickerResult[]> CompletedHandler { get; set; } public override void DidFinishPicking(PHPickerViewController picker, PHPickerResult[] results) => CompletedHandler?.Invoke(results?.Length > 0 ? results : null); } //TaskCompletionSource<Dictionary<string, string>> taskCompletionSource; //UIImagePickerController imagePicker; PHPickerViewController picPicker; async Task<Dictionary<string, string>> IPhotoPickerService.GetImageByIntent() { var dic = new Dictionary<string, string>(); picPicker = new PHPickerViewController(new PHPickerConfiguration { Filter = PHPickerFilter.ImagesFilter, SelectionLimit = 3, PreferredAssetRepresentationMode = PHPickerConfigurationAssetRepresentationMode.Automatic, }); var window = UIApplication.SharedApplication.KeyWindow; var vc = window.RootViewController; while (vc.PresentedViewController != null) { vc = vc.PresentedViewController; } var tcs = new TaskCompletionSource<(List<string>, List<string>)>(); picPicker.Delegate = new PPD { CompletedHandler = async res => { var resultd = await PickerResultsToMediaFile(res); tcs.TrySetResult(resultd); } }; await vc.PresentViewControllerAsync(picPicker, true); var resultTask = await tcs.Task; //var result = await resultTask; //var result = resultTask.Item1; //string base64String = Convert.ToBase64String(result); //var filename = resultTask.Item2; var base64Strings = resultTask.Item1; var filenames = resultTask.Item2; for (int i = 0; i < base64Strings.Count; i++) { dic.Add(filenames[i], base64Strings[i]); } await vc.DismissViewControllerAsync(true); picPicker?.Dispose(); //return result; return dic; } private async Task<(List<string>, List<string>)> PickerResultsToMediaFile(PHPickerResult[] res) { var results = new List<string>(); List<string> stringList = new List<string>(); var tcs = new TaskCompletionSource<NSObject>(); if (res != null) { foreach (var item in res) { try { var provider = item.ItemProvider; var suggestedName = provider.SuggestedName; var identifiers = provider?.RegisteredTypeIdentifiers; var identifier = (identifiers?.Any(i => i.StartsWith(UTType.LivePhoto)) ?? false) && (identifiers?.Contains(UTType.JPEG) ?? false) ? identifiers?.FirstOrDefault(i => i == UTType.JPEG) : identifiers?.FirstOrDefault(); if (string.IsNullOrWhiteSpace(identifier)) continue; var timestamp = DateTime.UtcNow.Ticks; var fileName = $"{timestamp}{provider?.SuggestedName}.{GetTag(identifier, UTType.TagClassFilenameExtension)}"; stringList.Add(fileName); var stream = (await provider.LoadDataRepresentationAsync(identifier))?.AsStream(); string tempFolderPath = Path.GetTempPath(); string filePath = Path.Combine(tempFolderPath, fileName); using (FileStream fs = new FileStream(filePath, FileMode.Create)) { stream.CopyTo(fs); results.Add(filePath); Console.WriteLine(filePath); } } catch (Exception) { continue; } } } return (results, stringList); } protected internal static string GetTag(string identifier, string tagClass) => UTType.CopyAllTags(identifier, tagClass)?.FirstOrDefault(); } }
2. 在上一片文章的基础上,我们在MauiProgram.cs里注册iOS的接口:
#if IOS builder.Services.AddSingleton<IPhotoPickerService, IOSPhotoPickerService>(); #endif
3. 同样在MainPage.xaml.cs里,补上上一篇文章提到的iOS需要的代码:
void blazorWebView_BlazorWebViewInitializing(System.Object sender, Microsoft.AspNetCore.Components.WebView.BlazorWebViewInitializingEventArgs e) { #if IOS e.Configuration.SetUrlSchemeHandler(new MySchemeHandler(), "myfile"); #endif } #if IOS private class MySchemeHandler : NSObject, IWKUrlSchemeHandler { [Export("webView:startURLSchemeTask:")] public void StartUrlSchemeTask(WKWebView webView, IWKUrlSchemeTask urlSchemeTask) { if (urlSchemeTask.Request.Url == null) { return; } var path = urlSchemeTask.Request.Url?.Path ?? ""; if (File.Exists(path)) { byte[] bytes = File.ReadAllBytes(path); using var response = new NSHttpUrlResponse(urlSchemeTask.Request.Url, 200, "HTTP/1.1", null); urlSchemeTask.DidReceiveResponse(response); urlSchemeTask.DidReceiveData(NSData.FromArray(bytes)); urlSchemeTask.DidFinish(); } } [Export("webView:stopURLSchemeTask:")] public void StopUrlSchemeTask(WKWebView webView, IWKUrlSchemeTask urlSchemeTask) { }
} #endif
4. 在Index.razor里,添加如下测试代码:
@page "/" @using AndroidPhotoPicker.Service <h1>Hello, world!</h1> Welcome to your new app. <button @onclick="GetImageAsync3">添加图片INTENT</button> @if (_phoneDictionary.Any()) { @foreach (var phone in _phoneDictionary) { <div style="height: 100%; width: 100%;"> <img src="@phone.Value" style="height:90px;width:90px;object-fit:cover;" /> </div> <div>图片名称: @phone.Key</div> } } @code{ [Inject] private IPhotoPickerService _photoPickerService { get; set; } //注入服务接口 private Dictionary<string, string> _phoneDictionary { get; set; } = new Dictionary<string, string>();//图片路径字典 private async Task GetImageAsync3() { var photoDic = await _photoPickerService.GetImageAsyncByIntent(); foreach (var photo in photoDic) { string iosUrl = "myfile://" + photo.Value; _phoneDictionary.Add(photo.Key, iosUrl ; } await InvokeAsync(StateHasChanged); } }
知识共享许可协议
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名Tony(包含链接: https://www.cnblogs.com/wecareu/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系 。
转载声明
本文来自博客园,作者:Tony,转载请注明原文链接:https://www.cnblogs.com/wecareu/p/17855489.html
本文来自博客园,作者:MTony,转载请注明原文链接:https://www.cnblogs.com/wecareu/p/17855489.html