Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在Xamarin.Forms中实现经典媒体选择器?_C#_Xamarin_Xamarin.forms - Fatal编程技术网

C# 如何在Xamarin.Forms中实现经典媒体选择器?

C# 如何在Xamarin.Forms中实现经典媒体选择器?,c#,xamarin,xamarin.forms,C#,Xamarin,Xamarin.forms,我正在开发这个xamarin.forms应用程序,它要求用户从其设备中选择一定数量的照片(从最少1张照片到指定的最大数量,甚至无限)。 我一直在努力了解如何实现这一点。 我使用了Microsoft文档中建议的图像编号,但这样我无法限制可选图像编号。 我还尝试在这两个项目中使用依赖性服务来实现图库,但我认为我走错了路:在android上,我在某些文件夹中搜索设备图像,但这样,如果用户的照片存储在外部应用程序(如谷歌照片或亚马逊照片)中,他无法查看(并选择)它们,他还没有在iOS上尝试过 以前我试过

我正在开发这个xamarin.forms应用程序,它要求用户从其设备中选择一定数量的照片(从最少1张照片到指定的最大数量,甚至无限)。 我一直在努力了解如何实现这一点。 我使用了Microsoft文档中建议的图像编号,但这样我无法限制可选图像编号。 我还尝试在这两个项目中使用依赖性服务来实现图库,但我认为我走错了路:在android上,我在某些文件夹中搜索设备图像,但这样,如果用户的照片存储在外部应用程序(如谷歌照片或亚马逊照片)中,他无法查看(并选择)它们,他还没有在iOS上尝试过

以前我试过使用lib,但从20年11月起lib就被取消了

我不明白这段代码是如何正确实现的,为什么在应用程序中如此普遍的情况下,没有一个视图来支持它


如何做到这一点?

如媒体上所述。插件:

Xamarin.Essentials 1.6引入了对拾取/提取的官方支持 使用新的媒体选择器API


根据您的描述,如果您想限制所选照片的数量,我建议您可以在OnActivityResult中查看这些数量。我提供了一个示例,您可以查看:

首先,为依赖项服务创建接口,以在.net标准项目中打开库

public interface IMediaService
{
    Task OpenGallery();
}
其次,在Android项目中,我创建了一个服务来处理照片库的打开,我还使用权限插件来检查和请求Android 6及更高版本中的权限

[assembly: Xamarin.Forms.Dependency(typeof(MediaService))]
namespace pickerimage.Droid
{
public class MediaService : Java.Lang.Object, IMediaService
{
    public async Task OpenGallery()
    {
        try
        {
            var status = await CrossPermissions.Current.CheckPermissionStatusAsync(Plugin.Permissions.Abstractions.Permission.Storage);
            if (status != PermissionStatus.Granted)
            {
                if (await CrossPermissions.Current.ShouldShowRequestPermissionRationaleAsync(Plugin.Permissions.Abstractions.Permission.Storage))
                {
                    Toast.MakeText(Xamarin.Forms.Forms.Context, "Need Storage permission to access to your photos.", ToastLength.Long).Show();
                }

                var results = await CrossPermissions.Current.RequestPermissionsAsync(new[] { Plugin.Permissions.Abstractions.Permission.Storage });
                status = results[Plugin.Permissions.Abstractions.Permission.Storage];
            }

            if (status == PermissionStatus.Granted)
            {
                Toast.MakeText(Xamarin.Forms.Forms.Context, "Select max 20 images", ToastLength.Long).Show();
                var imageIntent = new Intent(
                    Intent.ActionPick);
                imageIntent.SetType("image/*");
                imageIntent.PutExtra(Intent.ExtraAllowMultiple, true);
                imageIntent.SetAction(Intent.ActionGetContent);
                ((Activity)Forms.Context).StartActivityForResult(
                    Intent.CreateChooser(imageIntent, "Select photo"), 1);

            }
            else if (status != PermissionStatus.Unknown)
            {
                Toast.MakeText(Xamarin.Forms.Forms.Context, "Permission Denied. Can not continue, try again.", ToastLength.Long).Show();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
            Toast.MakeText(Xamarin.Forms.Forms.Context, "Error. Can not continue, try again.", ToastLength.Long).Show();
        }
    }
   
}
}

public static class ImageHelpers
{
    public static string SaveFile(string collectionName, byte[] imageByte, string fileName)
    {
        var fileDir = new Java.IO.File(Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryPictures), collectionName);
        if (!fileDir.Exists())
        {
            fileDir.Mkdirs();
        }

        var file = new Java.IO.File(fileDir, fileName);
        System.IO.File.WriteAllBytes(file.Path, imageByte);

        return file.Path;

    }

    public static byte[] RotateImage(string path)
    {
        byte[] imageBytes;

        var originalImage = BitmapFactory.DecodeFile(path);
        var rotation = GetRotation(path);
        var width = (originalImage.Width * 0.25);
        var height = (originalImage.Height * 0.25);
        var scaledImage = Bitmap.CreateScaledBitmap(originalImage, (int)width, (int)height, true);

        Bitmap rotatedImage = scaledImage;
        if (rotation != 0)
        {
            var matrix = new Matrix();
            matrix.PostRotate(rotation);
            rotatedImage = Bitmap.CreateBitmap(scaledImage, 0, 0, scaledImage.Width, scaledImage.Height, matrix, true);
            scaledImage.Recycle();
            scaledImage.Dispose();
        }

        using (var ms = new MemoryStream())
        {
            rotatedImage.Compress(Bitmap.CompressFormat.Jpeg, 90, ms);
            imageBytes = ms.ToArray();
        }

        originalImage.Recycle();
        rotatedImage.Recycle();
        originalImage.Dispose();
        rotatedImage.Dispose();
        GC.Collect();

        return imageBytes;
    }

    private static int GetRotation(string filePath)
    {
        using (var ei = new ExifInterface(filePath))
        {
            var orientation = (Android.Media.Orientation)ei.GetAttributeInt(ExifInterface.TagOrientation, (int)Android.Media.Orientation.Normal);

            switch (orientation)
            {
                case Android.Media.Orientation.Rotate90:
                    return 90;
                case Android.Media.Orientation.Rotate180:
                    return 180;
                case Android.Media.Orientation.Rotate270:
                    return 270;
                default:
                    return 0;
            }
        }
    }
}
 }
最后,在MainActivity.cs中,检查
clipData.ItemCount
count,如果count大于20,则返回

protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
    {
        base.OnActivityResult(requestCode, resultCode, data);

        if (requestCode == 1 && resultCode == Result.Ok)
        {
            List<string> images = new List<string>();

            if (data != null)
            {
                ClipData clipData = data.ClipData;
                if (clipData != null)
                {
                    if(clipData.ItemCount>20)
                    {
                        Toast.MakeText(Xamarin.Forms.Forms.Context, "please select max 20 images", ToastLength.Long).Show();
                        return;
                    }
                    for (int i = 0; i < clipData.ItemCount; i++)
                    {
                        ClipData.Item item = clipData.GetItemAt(i);
                        Android.Net.Uri uri = item.Uri;
                        var path = GetRealPathFromURI(uri);

                        if (path != null)
                        {
                            //Rotate Image
                            var imageRotated = ImageHelpers.RotateImage(path);
                            var newPath = ImageHelpers.SaveFile("TmpPictures", imageRotated, System.DateTime.Now.ToString("yyyyMMddHHmmssfff"));
                            images.Add(newPath);
                        }
                    }
                }
                else
                {
                    Android.Net.Uri uri = data.Data;
                    var path = GetRealPathFromURI(uri);

                    if (path != null)
                    {
                        //Rotate Image
                        var imageRotated = ImageHelpers.RotateImage(path);
                        var newPath = ImageHelpers.SaveFile("TmpPictures", imageRotated, System.DateTime.Now.ToString("yyyyMMddHHmmssfff"));
                        images.Add(newPath);
                    }
                }

                MessagingCenter.Send<App, List<string>>((App)Xamarin.Forms.Application.Current, "ImagesSelected", images);
            }
        }
    }



    public String GetRealPathFromURI(Android.Net.Uri contentURI)
    {
        try
        {
            ICursor imageCursor = null;
            string fullPathToImage = "";

            imageCursor = ContentResolver.Query(contentURI, null, null, null, null);
            imageCursor.MoveToFirst();
            int idx = imageCursor.GetColumnIndex(MediaStore.Images.ImageColumns.Data);

            if (idx != -1)
            {
                fullPathToImage = imageCursor.GetString(idx);
            }
            else
            {
                ICursor cursor = null;
                var docID = DocumentsContract.GetDocumentId(contentURI);
                var id = docID.Split(':')[1];
                var whereSelect = MediaStore.Images.ImageColumns.Id + "=?";
                var projections = new string[] { MediaStore.Images.ImageColumns.Data };

                cursor = ContentResolver.Query(MediaStore.Images.Media.InternalContentUri, projections, whereSelect, new string[] { id }, null);
                if (cursor.Count == 0)
                {
                    cursor = ContentResolver.Query(MediaStore.Images.Media.ExternalContentUri, projections, whereSelect, new string[] { id }, null);
                }
                var colData = cursor.GetColumnIndexOrThrow(MediaStore.Images.ImageColumns.Data);
                cursor.MoveToFirst();
                fullPathToImage = cursor.GetString(colData);
            }
            return fullPathToImage;
        }
        catch (Exception ex)
        {
            Toast.MakeText(Xamarin.Forms.Forms.Context, "Unable to get path", ToastLength.Long).Show();

        }

        return null;

    }
}
activityresult上的受保护覆盖无效(int-requestCode、Result-resultCode、Intent数据)
{
base.OnActivityResult(请求代码、结果代码、数据);
if(requestCode==1&&resultCode==Result.Ok)
{
列表图像=新列表();
如果(数据!=null)
{
ClipData ClipData=data.ClipData;
if(clipData!=null)
{
如果(clipData.ItemCount>20)
{
Toast.MakeText(Xamarin.Forms.Forms.Context,“请选择最多20个图像”,ToastLength.Long).Show();
返回;
}
对于(int i=0;i
在主页上显示图像

 <StackLayout>
    <Button
        BackgroundColor="Blue"
        Clicked="Handle_Clicked"
        Text="Select From Gallery"
        TextColor="White" />

    <ListView x:Name="listItems">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <StackLayout Orientation="Horizontal">
                        <Image HeightRequest="100" Source="{Binding .}" />
                    </StackLayout>
                </ViewCell>

            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

</StackLayout>

public partial class MainPage : ContentPage
{
    List<string> _images = new List<string>();
    public MainPage()
    {
        InitializeComponent();
    }
    protected override void OnAppearing()
    {
        base.OnAppearing();

        MessagingCenter.Subscribe<App, List<string>>((App)Xamarin.Forms.Application.Current, "ImagesSelected", (s, images) =>
        {
            listItems.ItemsSource = images;
            _images = images;
        });
    }
    protected override void OnDisappearing()
    {
        base.OnDisappearing();
        MessagingCenter.Unsubscribe<App, List<string>>(this, "ImagesSelected");
    }

    async void Handle_Clicked(object sender, System.EventArgs e)
    {
        await DependencyService.Get<IMediaService>().OpenGallery();
    }
}

公共部分类主页:ContentPage
{
列表_images=新列表();
公共主页()
{
初始化组件();
}
出现时受保护的覆盖无效()
{
base.OnAppearing();
MessagingCenter.Subscribe((App)Xamarin.Forms.Application.Curren