這篇文章主要介紹如何在Xamarin.Form實(shí)現(xiàn)跨平臺(tái)的調(diào)用系統(tǒng)圖片庫(kù)。
由于系統(tǒng)圖片庫(kù)是一個(gè)平臺(tái)相關(guān)性比較大的系統(tǒng)工具喷鸽,在Xamarin.Form上沒(méi)有現(xiàn)成的統(tǒng)一API可用,所以我們只能利用DependencyService
來(lái)自己實(shí)現(xiàn)一個(gè)對(duì)系統(tǒng)圖片庫(kù)的調(diào)用。
下面,我們就一步一步來(lái)實(shí)現(xiàn)這個(gè)DependencyService調(diào)用嚷那。
聲明接口
namespace DependencyServiceSample
{
public interface IPicturePicker
{
Task<Stream> GetImageStreamAsync();
}
}
這里我們將方法聲明為異步的,因?yàn)橹挥械鹊接脩?hù)選擇完圖片之后這個(gè)方法才會(huì)返回忌栅,聲明成異步方法才不至于阻塞主線(xiàn)程车酣。
iOS平臺(tái)下的實(shí)現(xiàn)
在iOS平臺(tái)下曲稼,我們要利用UIImagePickerController
來(lái)打開(kāi)圖片庫(kù)索绪。
[assembly: Dependency (typeof (PicturePickerImplementation))]
namespace DependencyServiceSample.iOS
{
public class PicturePickerImplementation : IPicturePicker
{
TaskCompletionSource<Stream> taskCompletionSource;
UIImagePickerController imagePicker;
public Task<Stream> GetImageStreamAsync()
{
// 創(chuàng)建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對(duì)象
taskCompletionSource = new TaskCompletionSource<Stream>();
return taskCompletionSource.Task;
}
void OnImagePickerFinishedPickingMedia(object sender, UIImagePickerMediaPickedEventArgs args)
{
UIImage image = args.EditedImage ?? args.OriginalImage;
if (image != null)
{
//將 UIImage轉(zhuǎn)換成 .NET Stream對(duì)象
NSData data = image.AsJPEG(1);
Stream stream = data.AsStream();
// 將Stream設(shè)置為T(mén)ask的結(jié)果
taskCompletionSource.SetResult(stream);
}
else
{
taskCompletionSource.SetResult(null);
}
imagePicker.DismissModalViewController(true);
}
void OnImagePickerCancelled(object sender, EventArgs args)
{
taskCompletionSource.SetResult(null);
imagePicker.DismissModalViewController(true);
}
}
}
為了使程序可以正常運(yùn)行,我們還需要在plist文件中的dict
段里添加如下聲明:
<key>NSPhotoLibraryUsageDescription</key>
<string>Picture Picker uses photo library</string>
Android平臺(tái)下的實(shí)現(xiàn)
在Android平臺(tái)下贫悄,我們要聲明一個(gè)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設(shè)置為T(mén)ask的結(jié)果
PickImageTaskCompletionSource.SetResult(stream);
}
else
{
PickImageTaskCompletionSource.SetResult(null);
}
}
}
}
還有圖片選擇器的實(shí)現(xiàn):
[assembly: Dependency(typeof(PicturePickerImplementation))]
namespace DependencyServiceSample.Droid
{
public class PicturePickerImplementation : IPicturePicker
{
public Task<Stream> GetImageStreamAsync()
{
// 定義一個(gè)用于獲取圖片的Intent
Intent intent = new Intent();
intent.SetType("image/*");
intent.SetAction(Intent.ActionGetContent);
// 獲取MainActivity的實(shí)例
MainActivity activity = Forms.Context as MainActivity;
//啟動(dòng)圖片選擇的 activity (選擇結(jié)果在MainActivity.cs中處理)
activity.StartActivityForResult(
Intent.CreateChooser(intent, "Select Picture"),
MainActivity.PickImageId);
// 保存一個(gè)TaskCompletionSource 對(duì)象作為 MainActivity的屬性
activity.PickImageTaskCompletionSource = new TaskCompletionSource<Stream>();
// 返回 Task 對(duì)象
return activity.PickImageTaskCompletionSource.Task;
}
}
}
在Xamarin.Form中調(diào)用圖片選擇器
Stream stream = await DependencyService.Get<IPicturePicker>().GetImageStreamAsync();
if (stream != null)
{
Image image = new Image
{
Source = ImageSource.FromStream(() => stream)
};
}