我是靠谱客的博主 欢呼项链,最近开发中收集的这篇文章主要介绍xamarin android上传图片到服务器,从图片库中选取照片,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

从图片库中选取照片Picking a Photo from the Picture Library

03/06/2017

本文内容

本文介绍如何创建一种应用程序,使用户可通过该应用程序从手机的图片库中选取照片。This article walks through the creation of an application that allows the user to pick a photo from the phone's picture library. 由于 Xamarin.Forms 不包含此功能,因此有必要使用 DependencyService 来访问每个平台上的本机 API。Because Xamarin.Forms does not include this functionality, it is necessary to use DependencyService to access native APIs on each platform.

创建界面Creating the interface

首先,在表示所需功能的共享代码中创建接口。First, create an interface in shared code that expresses the desired functionality. 如果是照片选取应用程序,只需要一种方法。In the case of a photo-picking application, just one method is required. 该方法在示例代码的 .NET Standard 库中的 IPhotoPickerService 接口进行定义:This is defined in the IPhotoPickerService interface in the .NET Standard library of the sample code:

namespace DependencyServiceDemos

{

public interface IPhotoPickerService

{

Task GetImageStreamAsync();

}

}

GetImageStreamAsync 方法定义为异步,因为该方法必须快速返回,但是不能为所选照片返回 Stream 对象,除非用户浏览了图片库并选择了一张照片。The GetImageStreamAsync method is defined as asynchronous because the method must return quickly, but it can't return a Stream object for the selected photo until the user has browsed the picture library and selected one.

该接口使用特定于平台的代码在所有平台上实现。This interface is implemented in all the platforms using platform-specific code.

iOS 实现iOS implementation

IPhotoPickerService 接口的 iOS 实现使用 UIImagePickerController,正如“从库中选择照片”方案和示例代码中描述那样。The iOS implementation of the IPhotoPickerService interface uses the UIImagePickerController as described in the Choose a Photo from the Gallery recipe and sample code.

iOS 实现包含在示例代码的 iOS 项目中的 PhotoPickerService 类中。The iOS implementation is contained in the PhotoPickerService class in the iOS project of the sample code. 为了使该类对 DependencyService 管理器可见,此类必须被标识为 Dependency 类型的 [assembly] 属性,且该类必须是公共的,并显式地实现 IPhotoPickerService 接口:To make this class visible to the DependencyService manager, the class must be identified with an [assembly] attribute of type Dependency, and the class must be public and explicitly implement the IPhotoPickerService interface:

[assembly: Dependency (typeof (PhotoPickerService))]

namespace DependencyServiceDemos.iOS

{

public class PhotoPickerService : IPhotoPickerService

{

TaskCompletionSource taskCompletionSource;

UIImagePickerController imagePicker;

public Task GetImageStreamAsync()

{

// Create and define UIImagePickerController

imagePicker = new UIImagePickerController

{

SourceType = UIImagePickerControllerSourceType.PhotoLibrary,

MediaTypes = UIImagePickerController.AvailableMediaTypes(UIImagePickerControllerSourceType.PhotoLibrary)

};

// Set event handlers

imagePicker.FinishedPickingMedia += OnImagePickerFinishedPickingMedia;

imagePicker.Canceled += OnImagePickerCancelled;

// Present UIImagePickerController;

UIWindow window = UIApplication.SharedApplication.KeyWindow;

var viewController = window.RootViewController;

viewController.PresentViewController(imagePicker, true, null);

// Return Task object

taskCompletionSource = new TaskCompletionSource();

return taskCompletionSource.Task;

}

...

}

}

GetImageStreamAsync 方法创建 UIImagePickerController 并初始化它,以从照片库中选择图像。The GetImageStreamAsync method creates a UIImagePickerController and initializes it to select images from the photo library. 需要两个事件处理程序:一个用于用户选择照片,另一个用于用户取消照片库的显示。Two event handlers are required: One for when the user selects a photo and the other for when the user cancels the display of the photo library. 然后 PresentViewController 方法向用户显示照片图库。The PresentViewController method then displays the photo library to the user.

此时,GetImageStreamAsync 方法必须将 Task 对象返回给调用它的代码。At this point, the GetImageStreamAsync method must return a Task object to the code that's calling it. 只有用户已完成与照片库的交互并调用其中一个事件处理程序时,该任务才会完成。This task is completed only when the user has finished interacting with the photo library and one of the event handlers is called. For situations like this, the TaskCompletionSource class is essential. 该类提供要从 GetImageStreamAsync 方法返回的适当泛型类型的 Task 对象,稍后完成任务时该类将收到通知。The class provides a Task object of the proper generic type to return from the GetImageStreamAsync method, and the class can later be signaled when the task is completed.

用户已选择图片时,将调用 FinishedPickingMedia 事件处理程序。The FinishedPickingMedia event handler is called when the user has selected a picture. 但是,处理程序提供 UIImage 对象,而 Task 必须返回 .NET Stream 对象。However, the handler provides a UIImage object and the Task must return a .NET Stream object. 这需要执行两个步骤来完成:首先将 UIImage 对象转换为存储在 NSData 对象中的内存中 PNG 或 JPEG 文件,然后将 NSData 对象转换为 .NET Stream 对象。This is done in two steps: The UIImage object is first converted to an in memory PNG or JPEG file stored in an NSData object, and then the NSData object is converted to a .NET Stream object. 通过调用 TaskCompletionSource 对象的 SetResult 方法,以提供 Stream 对象的方式完成任务:A call to the SetResult method of the TaskCompletionSource object completes the task by providing the Stream object:

namespace DependencyServiceDemos.iOS

{

public class PhotoPickerService : IPhotoPickerService

{

TaskCompletionSource taskCompletionSource;

UIImagePickerController imagePicker;

...

void OnImagePickerFinishedPickingMedia(object sender, UIImagePickerMediaPickedEventArgs args)

{

UIImage image = args.EditedImage ?? args.OriginalImage;

if (image != null)

{

// Convert UIImage to .NET Stream object

NSData data;

if (args.ReferenceUrl.PathExtension.Equals("PNG") || args.ReferenceUrl.PathExtension.Equals("png"))

{

data = image.AsPNG();

}

else

{

data = image.AsJPEG(1);

}

Stream stream = data.AsStream();

UnregisterEventHandlers();

// Set the Stream as the completion of the Task

taskCompletionSource.SetResult(stream);

}

else

{

UnregisterEventHandlers();

taskCompletionSource.SetResult(null);

}

imagePicker.DismissModalViewController(true);

}

void OnImagePickerCancelled(object sender, EventArgs args)

{

UnregisterEventHandlers();

taskCompletionSource.SetResult(null);

imagePicker.DismissModalViewController(true);

}

void UnregisterEventHandlers()

{

imagePicker.FinishedPickingMedia -= OnImagePickerFinishedPickingMedia;

imagePicker.Canceled -= OnImagePickerCancelled;

}

}

}

iOS 应用程序需要用户的许可才能访问手机的照片库。An iOS application requires permission from the user to access the phone's photo library. 将以下内容添加到 Info.plist 文件的 dict 部分:Add the following to the dict section of the Info.plist file:

NSPhotoLibraryUsageDescription

Picture Picker uses photo library

Android 实现Android implementation

Android 实现使用选择图像方案和示例代码中描述的技术。The Android implementation uses the technique described in the Select an Image recipe and the sample code. 但是,如果用户已选择图片库中的图像,则调用的方法是派生自 Activity 的类中的 OnActivityResult 替代。However, the method that is called when the user has selected an image from the picture library is an OnActivityResult override in a class that derives from Activity. 因此,Android 项目中的常规 MainActivity 类补充了一个字段、一个属性和 OnActivityResult 方法的一个替代:For this reason, the normal MainActivity class in the Android project has been supplemented with a field, a property, and an override of the OnActivityResult method:

public class MainActivity : FormsAppCompatActivity

{

internal static MainActivity Instance { get; private set; }

protected override void OnCreate(Bundle savedInstanceState)

{

// ...

Instance = this;

}

// ...

// Field, property, and method for Picture Picker

public static readonly int PickImageId = 1000;

public TaskCompletionSource 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);

// Set the Stream as the completion of the Task

PickImageTaskCompletionSource.SetResult(stream);

}

else

{

PickImageTaskCompletionSource.SetResult(null);

}

}

}

}

OnActivityResult 替代指示所选图片文件具有 Android Uri 对象,但是可以通过调用从活动的 ContentResolver 属性中获得的 ContentResolver 对象的 OpenInputStream 方法将其转换为 .NET Stream 对象。The OnActivityResultoverride indicates the selected picture file with an Android Uri object, but this can be converted into a .NET Stream object by calling the OpenInputStream method of the ContentResolver object that was obtained from the activity's ContentResolver property.

与 iOS 实现一样,任务完成时,Android 实现将使用 TaskCompletionSource 进行通知。Like the iOS implementation, the Android implementation uses a TaskCompletionSource to signal when the task has been completed. 该 TaskCompletionSource 对象在 MainActivity 类中定义为公共属性。This TaskCompletionSource object is defined as a public property in the MainActivity class. 这样便可在 Android 项目中的 PhotoPickerService 类中引用该属性。This allows the property to be referenced in the PhotoPickerService class in the Android project. 这是使用 GetImageStreamAsync 方法的类:This is the class with the GetImageStreamAsync method:

[assembly: Dependency(typeof(PhotoPickerService))]

namespace DependencyServiceDemos.Droid

{

public class PhotoPickerService : IPhotoPickerService

{

public Task GetImageStreamAsync()

{

// Define the Intent for getting images

Intent intent = new Intent();

intent.SetType("image/*");

intent.SetAction(Intent.ActionGetContent);

// Start the picture-picker activity (resumes in MainActivity.cs)

MainActivity.Instance.StartActivityForResult(

Intent.CreateChooser(intent, "Select Picture"),

MainActivity.PickImageId);

// Save the TaskCompletionSource object as a MainActivity property

MainActivity.Instance.PickImageTaskCompletionSource = new TaskCompletionSource();

// Return Task object

return MainActivity.Instance.PickImageTaskCompletionSource.Task;

}

}

}

该方法访问 MainActivity 类有几个目的:实现 Instance 属性、PickImageId 字段、TaskCompletionSource 属性,以及调用 StartActivityForResult。This method accesses the MainActivity class for several purposes: for the Instance property, for the PickImageId field, for the TaskCompletionSource property, and to call StartActivityForResult. 该方法是由 FormsAppCompatActivity 类定义的,此类是 MainActivity 的基类。This method is defined by the FormsAppCompatActivity class, which is the base class of MainActivity.

UWP 实现UWP implementation

与 iOS 和 Android 实现不同,用于通用 Windows 平台的照片选取器的实现不需要 TaskCompletionSource 类。Unlike the iOS and Android implementations, the implementation of the photo picker for the Universal Windows Platform does not require the TaskCompletionSource class. The PhotoPickerService class uses the FileOpenPicker class to get access to the photo library. 由于 FileOpenPicker 的 PickSingleFileAsync 方法本身是异步的,GetImageStreamAsync 方法可以简单地将 await 与该方法(以及其他异步方法)一起使用,并返回 Stream 对象:Because the PickSingleFileAsync method of FileOpenPicker is itself asynchronous, the GetImageStreamAsync method can simply use await with that method (and other asynchronous methods) and return a Stream object:

[assembly: Dependency(typeof(PhotoPickerService))]

namespace DependencyServiceDemos.UWP

{

public class PhotoPickerService : IPhotoPickerService

{

public async Task GetImageStreamAsync()

{

// Create and initialize the FileOpenPicker

FileOpenPicker openPicker = new FileOpenPicker

{

ViewMode = PickerViewMode.Thumbnail,

SuggestedStartLocation = PickerLocationId.PicturesLibrary,

};

openPicker.FileTypeFilter.Add(".jpg");

openPicker.FileTypeFilter.Add(".jpeg");

openPicker.FileTypeFilter.Add(".png");

// Get a file and return a Stream

StorageFile storageFile = await openPicker.PickSingleFileAsync();

if (storageFile == null)

{

return null;

}

IRandomAccessStreamWithContentType raStream = await storageFile.OpenReadAsync();

return raStream.AsStreamForRead();

}

}

}

在共享代码中实现Implementing in shared code

为每个平台实现接口后,现在 .NET Standard 库中的共享代码即可利用该接口。Now that the interface has been implemented for each platform, the shared code in the .NET Standard library can take advantage of it.

UI 包含可通过单击选择照片的 Button:The UI includes a Button that can be clicked to choose a photo:

Clicked="OnPickPhotoButtonClicked" />

Clicked 事件处理程序使用 DependencyService 类调用 GetImageStreamAsync。The Clicked event handler uses the DependencyService class to call GetImageStreamAsync. 这会导致调用平台项目。This results in a call to the platform project. 如果该方法返回 Stream 对象,则处理程序会将 image 对象的 Source 属性设置为 Stream 数据:If the method returns a Stream object, then the handler sets the Source property of the image object to the Stream data:

async void OnPickPhotoButtonClicked(object sender, EventArgs e)

{

(sender as Button).IsEnabled = false;

Stream stream = await DependencyService.Get().GetImageStreamAsync();

if (stream != null)

{

image.Source = ImageSource.FromStream(() => stream);

}

(sender as Button).IsEnabled = true;

}

相关链接Related links

最后

以上就是欢呼项链为你收集整理的xamarin android上传图片到服务器,从图片库中选取照片的全部内容,希望文章能够帮你解决xamarin android上传图片到服务器,从图片库中选取照片所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(50)

评论列表共有 0 条评论

立即
投稿
返回
顶部