Xamarin.Form跨平台访问系统图片库

作者: 临岁之寒 | 来源:发表于2017-06-21 08:41 被阅读141次

这篇文章主要介绍如何在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)
        };
    }

参考文献

Picking a Photo from the Picture Library

相关文章

  • Xamarin.Form跨平台访问系统图片库

    这篇文章主要介绍如何在Xamarin.Form实现跨平台的调用系统图片库。由于系统图片库是一个平台相关性比较大的系...

  • Xamarin.Form下WebView在iOS平台上的使用方法

    Xamarin.Form的好处是可以开发跨平台的应用,但针对不同的平台,还需要做一些调整。如果你对Xamarin不...

  • 用DependencyService实现跨平台开发

    Xamarin.Form目前是微软提供的一种跨平台的开发技术,可以让开发者在iOS、Android和Window ...

  • py3笔记22:OS常用命令

    1. OS模块介绍 Python标准库用于访问操作系统相关功能作用:实现跨平台访问:包括大量操作系统的函数主要功能...

  • 产品计划

    打算做出一款监督自己实现目标的app,希望时间能在年前实现。由于Xamarin.Form跨平台有mac调试的要求,...

  • python之os模块

    os模块是Python标准库中的一个用于访问操作系统功能的模块,使用os模块中提供的接口,可以实现跨平台访问,通用...

  • SDL简介和使用

    SDL 跨平台硬件访问 Simple DirectMedia(SDL)Layer 是一个跨平台开发库,旨在通过 O...

  • 文件系统

    对于文件系统的访问,python一般是通过OS(操作系统)模块实现的。python作为跨平台的语言,在不同的操作系...

  • JAVA学习笔记1

    1.java的跨平台java能跨平台是因为JVM,java语言可以跨平台,JVM不能跨平台对于不同的系统,有不同的...

  • flutter-对跨平台的理解

    一、跨平台语言 1、对跨平台的理解(跨操作系统) java语言的跨平台说白了是让程序员用户可以跨平台,它的平台移植...

网友评论

    本文标题:Xamarin.Form跨平台访问系统图片库

    本文链接:https://www.haomeiwen.com/subject/tymbfxtx.html