Xamarin iOS分享扩展获取图片后无法绑定显示的问题求助
Xamarin.Forms 5分享扩展图片绑定显示失败问题解决
我使用Xamarin.Forms 5.X.X创建了Demo应用,并开发了分享扩展,目前能成功获取到图片的文件路径,但尝试两种方式均无法在页面绑定显示图片:
- 通过
ImageResource.FromFile绑定文件路径 - 通过流绑定
相关代码
CustomShareViewController代码
public class CustomShareViewController: SLComposeServiceViewController { public CustomShareViewController(IntPtr handle) : base(handle) { } public override void DidReceiveMemoryWarning() { base.DidReceiveMemoryWarning(); } public override async void ViewDidLoad() { base.ViewDidLoad(); string urlstr = string.Empty; NSExtensionItem item = ExtensionContext.InputItems[0]; var itemProvider = item.Attachments[0]; var type = itemProvider.Description.Split('"'); if (itemProvider.HasItemConformingTo(type[1])) { var load = await itemProvider.LoadItemAsync(type[1], null); NSUrl newUrl = (NSUrl)load; urlstr = newUrl.FilePathUrl.ToString(); } if (!Xamarin.Forms.Forms.IsInitialized) Xamarin.Forms.Forms.Init(); var xfPage = new ShareMainPage(); var viewModel = (ShareMainPageViewModel)xfPage.BindingContext; viewModel.Message = urlstr; viewModel.Image = urlstr; //viewModel.BindableImage = ImageSource.FromStream(() => new MemoryStream(byteArray)); viewModel.DoCommand = new Command(() => DoneClicked()); var newController = xfPage.CreateViewController(); newController.ModalPresentationStyle = UIModalPresentationStyle.FormSheet; this.PresentModalViewController(newController, false); } public override bool ShouldInteractWithUrl(UITextView textView, NSUrl url, NSRange characterRange, UITextItemInteraction interaction) { return base.ShouldInteractWithUrl(textView, url, characterRange, interaction); } public override bool IsContentValid() { return true; } public override void DidSelectPost() { } public override void PresentationAnimationDidFinish() { base.PresentationAnimationDidFinish(); } private void DoneClicked() { ExtensionContext.CompleteRequest(ExtensionContext.InputItems, null); } private void WriteToDebugFile(string dbgText) { var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); var filename = Path.Combine(documents, "Share-Extension-Debug.txt"); if (!File.Exists(filename)) { File.WriteAllText(filename, $"\n{DateTime.Now} - {dbgText}"); } else { File.AppendAllText(filename, $"\n{DateTime.Now} - {dbgText}"); } } }
ShareMainPage的XAML代码
<?xml version="1.0" encoding="UTF-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:Demo.ViewModels" x:DataType="local:ShareMainPageViewModel" xmlns:converters="clr-namespace:LifeApp.Mobile.Converters" BackgroundColor="Green" x:Class="LifeApp.Mobile.Views.ShareMainPage"> <ContentPage.BindingContext> <local:ShareMainPageViewModel Message="Hello from Xamarin.Forms!" /> </ContentPage.BindingContext> <ContentPage.Content> <StackLayout HorizontalOptions="Center" VerticalOptions="Center"> <Image Source="{Binding BindableImage}" VerticalOptions="Start" HorizontalOptions="CenterAndExpand" WidthRequest="200" HeightRequest="150"/> <Label Text="{Binding Message}" TextColor="Black" FontSize="Medium" VerticalTextAlignment="Center"/> <Button Command="{Binding DoCommand}" Text="Do the jungle!" TextColor="Black" /> </StackLayout> </ContentPage.Content> </ContentPage>
ShareMainPageViewModel代码
using System; using System.ComponentModel; using System.IO; using System.Windows.Input; using Xamarin.Essentials; using Xamarin.Forms; using Xamarin.Forms.Shapes; namespace Demo.ViewModels { public class ShareMainPageViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private string _message; public string Message { get { return _message; } set { if (_message != value) { _message = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Message))); } } } private string _image; public string Image { get { return _image; } set { if (_image != value) { _image = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Image))); } } } public ImageSource _bindableImage { get; set; } public ImageSource BindableImage { get { return _bindableImage; } set { if (_bindableImage !=null) { _bindableImage = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(BindableImage))); } } } private ICommand _doCommand; public ICommand DoCommand { get { return _doCommand; } set { if (_doCommand != value) { _doCommand = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(DoCommand))); } } } public ShareMainPageViewModel() { DoCommand = new Command(OnDoCommandExecuted); } private void OnDoCommandExecuted(object state) { Message = $"Job {Environment.TickCount} has been completed!"; } } }
获取到的图片路径示例:file:///Users/xxxx/Library/Developer/CoreSimulator/Devices/58453DF3-58CF-4591-AC91-6A096FD7B814/data/Containers/Data/Application/1466F475-0F58-4F94-8511-B0BD9FE86DCA/tmp/WKFileShare-FbFp8eSD/adcf0796-2088-4d85-9420-c1d58c15cca4/....JPG
解决方法
1. 修正文件路径处理
获取到的路径是带file://前缀的URL,ImageSource.FromFile需要的是本地文件路径(不带scheme),修改CustomShareViewController中的路径处理代码:
// 替换原来的urlstr = newUrl.FilePathUrl.ToString(); urlstr = newUrl.FilePathUrl.Path;
2. 修复ViewModel的BindableImage属性setter逻辑
当前setter中判断if (_bindableImage !=null)会导致第一次赋值时不触发PropertyChanged,UI无法更新,修改为:
public ImageSource BindableImage { get { return _bindableImage; } set { if (_bindableImage != value) { _bindableImage = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(BindableImage))); } } }
3. 选择合适的绑定方式
方式一:文件路径绑定
在CustomShareViewController中给ViewModel赋值:
viewModel.BindableImage = ImageSource.FromFile(urlstr);
方式二:流绑定
读取文件字节流后赋值:
byte[] imageBytes = File.ReadAllBytes(urlstr); viewModel.BindableImage = ImageSource.FromStream(() => new MemoryStream(imageBytes));
额外说明
iOS分享扩展默认拥有临时目录的访问权限,处理后的路径无需额外权限配置即可访问。
内容的提问来源于stack exchange,提问作者muhammetsahin
相关产品推荐
相关产品推荐

