Xamarin.Form跨平台访问系统图片库
这篇文章主要介绍如何在Xamarin.Form实现跨平台的调用系统图片库。 由于系统图片库是一个平台相关性比较大的系统工具,在Xamarin.Form上没有现成的统一API可用,所以我们只能利用DependencyService 来自己实现一个对系统图片库的调用。
下面,我们就一步一步来实现这个DependencyService调用。
声明接口
namespace DependencyServiceSample
{
public interface IPicturePicker
{
Task<Stream> GetImageStreamAsync();
}
}
这里我们将方法声明为异步的,因为只有等到用户选择完图片之后这个方法才会返回,声明成异步方法才不至于阻塞主线程。
iOS平台下的实现
在iOS平台下,我们要利用UIImagePickerController 来打开图片库。
[assembly: Dependency (typeof (PicturePickerImplementation))]
namespace DependencyServiceSample.iOS
{
public class PicturePickerImplementation : IPicturePicker
{
TaskCompletionSource<Stream> taskCompletionSource;
UIImagePickerController imagePicker;
public Task<Stream> GetImageStreamAsync()
{
// 创建UIImagePickerController
imagePicker = new UIImagePickerController
{
SourceType = UIImagePickerControllerSourceType.PhotoLibrary,
MediaTypes = UIImagePickerController.AvailableMediaTypes(UIImagePickerControllerSourceType.PhotoLibrary)
};
// 添加事件处理
imagePicker.FinishedPickingMedia += OnImagePickerFinishedPickingMedia;
imagePicker.Canceled += OnImagePickerCancelled;
// 显示UIImagePickerController;
UIWindow window = UIApplication.SharedApplication.KeyWindow;
var viewController = window.RootViewController;
viewController.PresentModalViewController(imagePicker, true);
// 返回Task对象
taskCompletionSource = new TaskCompletionSource<Stream>();
return taskCompletionSource.Task;
}
void OnImagePickerFinishedPickingMedia(object sender, UIImagePickerMediaPickedEventArgs args)
{
UIImage image = args.EditedImage ?? args.OriginalImage;
if (image != null)
{
//将 UIImage转换成 .NET Stream对象
NSData data = image.AsJPEG(1);
Stream stream = data.AsStream();
// 将Stream设置为Task的结果
taskCompletionSource.SetResult(stream);
}
else
{
taskCompletionSource.SetResult(null);
}
imagePicker.DismissModalViewController(true);
}
void OnImagePickerCancelled(object sender, EventArgs args)
{
taskCompletionSource.SetResult(null);
imagePicker.DismissModalViewController(true);
}
}
}
为了使程序可以正常运行,我们还需要在plist文件中的dict
段里添加如下声明:
<key>NSPhotoLibraryUsageDescription</key>
<string>Picture Picker uses photo library</string>
Android平台下的实现
在Android平台下,我们要声明一个Activity。
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
{
...
// 以下是为图片选择器而声明的字段、属性和方法
public static readonly int PickImageId = 1000;
public TaskCompletionSource<Stream> PickImageTaskCompletionSource { set; get; }
protected override void OnActivityResult(int requestCode, Result resultCode, Intent intent)
{
base.OnActivityResult(requestCode, resultCode, intent);
if (requestCode == PickImageId)
{
if ((resultCode == Result.Ok) && (intent != null))
{
Android.Net.Uri uri = intent.Data;
Stream stream = ContentResolver.OpenInputStream(uri);
// 将Stream设置为Task的结果
PickImageTaskCompletionSource.SetResult(stream);
}
else
{
PickImageTaskCompletionSource.SetResult(null);
}
}
}
}
还有图片选择器的实现:
[assembly: Dependency(typeof(PicturePickerImplementation))]
namespace DependencyServiceSample.Droid
{
public class PicturePickerImplementation : IPicturePicker
{
public Task<Stream> GetImageStreamAsync()
{
// 定义一个用于获取图片的Intent
Intent intent = new Intent();
intent.SetType("image/*");
intent.SetAction(Intent.ActionGetContent);
// 获取MainActivity的实例
MainActivity activity = Forms.Context as MainActivity;
//启动图片选择的 activity (选择结果在MainActivity.cs中处理)
activity.StartActivityForResult(
Intent.CreateChooser(intent, "Select Picture"),
MainActivity.PickImageId);
// 保存一个TaskCompletionSource 对象作为 MainActivity的属性
activity.PickImageTaskCompletionSource = new TaskCompletionSource<Stream>();
// 返回 Task 对象
return activity.PickImageTaskCompletionSource.Task;
}
}
}
在Xamarin.Form中调用图片选择器
Stream stream = await DependencyService.Get<IPicturePicker>().GetImageStreamAsync();
if (stream != null)
{
Image image = new Image
{
Source = ImageSource.FromStream(() => stream)
};
}
参考文献
- 原文作者:岁寒
- 原文链接:http://www.suihanime.com/post/Xamarin/Xamarin.Form%E8%B7%A8%E5%B9%B3%E5%8F%B0%E8%AE%BF%E9%97%AE%E7%B3%BB%E7%BB%9F%E5%9B%BE%E7%89%87%E5%BA%93/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。