【问题标题】:Xamarin forms: How to implement image cropping after selecting a picture from gallery or cameraXamarin 表单:如何在从图库或相机中选择图片后实现图像裁剪
【发布时间】:2021-02-02 02:11:26
【问题描述】:

我正在使用MediaPlugin 打开相机和图库以选择图片。选择图片后,我需要在将其设置到 UI 之前对其进行裁剪。我在相机中试过AllowCropping = true,但它只适用于windows和ios。对于所有平台(android、ios 和 windows)的 android 和图库中的相机,没有裁剪选项。

我尝试了ImageCropper.Forms 包来实现图像裁剪功能。

我的代码:

//Camera
async void CameraClick()
{
    try
    {
        await CrossMedia.Current.Initialize();

        if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
        {
            if (!Utility.IsWindowsDevice())
            {
                await DisplayAlert("Alert", "No camera available.", "Ok");
            }
            else
            {
                ShowAlert("No camera available.");
            }
            return;
        }

        _mediaFile = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions
        {
            Directory = "Sample",
            Name = "test.jpg",
            AllowCropping = true,
            PhotoSize = PhotoSize.Medium
        });

        if (_mediaFile == null)
            return;
        profilephoto.Source = ImageSource.FromStream(() =>
        {
            isPicture = true;
            isAvatar = false;
            if (Device.OS == TargetPlatform.iOS)
            {
                return _mediaFile.GetStreamWithImageRotatedForExternalStorage();
            }
            else
            {
                return _mediaFile.GetStream();
            }
        });

        new ImageCropper()
        {
            PageTitle = "Test Title",
            AspectRatioX = 1,
            AspectRatioY = 1,
            CropShape = ImageCropper.CropShapeType.Rectangle,
            SelectSourceTitle = "Select source",
            TakePhotoTitle = "Take Photo",
            PhotoLibraryTitle = "Photo Library",
            Success = (imageFile) =>
            {
                Device.BeginInvokeOnMainThread(() =>
                {
                    profilephoto.Source = ImageSource.FromFile(imageFile);
                });
            }
        }.Show(this);
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine("Exception:>" + ex);
    }
}

//Gallery
async void GalleryClick()
{
    try
    {
        await CrossMedia.Current.Initialize();

        if (!CrossMedia.Current.IsPickPhotoSupported)
        {
            if (!Utility.IsWindowsDevice())
            {
                await DisplayAlert("Alert", "No photos available.", "Ok");
            }
            else
            {
                ShowAlert("No photos available.");
            }
            return;
        }

        _mediaFile = await CrossMedia.Current.PickPhotoAsync(new PickMediaOptions
        {
            PhotoSize = PhotoSize.Medium
        });

        if (_mediaFile == null)
            return;
        profilephoto.Source = ImageSource.FromStream(() =>
        {
            isPicture = true;
            isAvatar = false;
            return _mediaFile.GetStream();
        });

        new ImageCropper()
        {
            PageTitle = "Test Title",
            AspectRatioX = 1,
            AspectRatioY = 1,
            CropShape = ImageCropper.CropShapeType.Rectangle,
            SelectSourceTitle = "Select source",
            TakePhotoTitle = "Take Photo",
            PhotoLibraryTitle = "Photo Library",
            Success = (imageFile) =>
            {
                Device.BeginInvokeOnMainThread(() =>
                {
                    profilephoto.Source = ImageSource.FromFile(imageFile);
                });
            }
        }.Show(this);
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine("Exception:>" + ex);
    }
}

我已经按照博客做了所有事情,但是当我运行时出现以下异常。

[0:] 异常:>System.MissingMethodException:找不到方法:System.Threading.Tasks.Task`1 Plugin.Media.Abstractions.IMedia.TakePhotoAsync(Plugin.Media. Abstractions.StoreCameraMediaOptions) 在 System.Runtime.CompilerServices.AsyncVoidMethodBuilder.Start[TStateMachine] (TStateMachine& stateMachine) [0x0002c] 在 /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/mcs/class/referencesource/mscorlib/系统/运行时/compilerservices/AsyncMethodBuilder.cs:84 在 Stormlion.ImageCropper.ImageCropper.Show (Xamarin.Forms.Page 页面,System.String imageFile) [0x00033] 在 :0 在 F:\My Projects\Xamarin\ProjectName\ProjectName\ProjectName\Pages\ProfilePage.xaml.cs:554 中的 ProjectName.Pages.ProfilePage.GalleryClick () [0x00227] 处

[0:] 异常:>System.MissingMethodException:找不到方法:System.Threading.Tasks.Task`1 Plugin.Media.Abstractions.IMedia.TakePhotoAsync(Plugin.Media. Abstractions.StoreCameraMediaOptions) 在 System.Runtime.CompilerServices.AsyncVoidMethodBuilder.Start[TStateMachine] (TStateMachine& stateMachine) [0x0002c] 在 /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/mcs/class/referencesource/mscorlib/系统/运行时/compilerservices/AsyncMethodBuilder.cs:84 在 Stormlion.ImageCropper.ImageCropper.Show (Xamarin.Forms.Page 页面,System.String imageFile) [0x00033] 在 :0 在 F:\My Projects\Xamarin\ProjectName\ProjectName\ProjectName\Pages\ProfilePage.xaml.cs:515 中的 ProjectName.Pages.ProfilePage.CameraClick () [0x0025b] 01-20 12:21:23.149 D/Mono (11820): 请求加载 System.Collections.dll 的引用 1(共 3 个)

不知道这背后的问题是什么。有没有其他简单的包来实现图片裁剪功能?

【问题讨论】:

  • 不使用 ImageCropper.Forms 包是否可以工作?
  • 你可以分享你的样品,这样我就可以在我身边测试它。
  • @LucasZhang-MSFT 我会准备样品并尽快与您分享。

标签: xamarin.forms camera gallery


【解决方案1】:

首先,将 ImageCropper.Forms.Fix.v2 nuget 包添加到您的项目中。

那么,如果你使用AndroidX,请修改AndroidManifest.xaml标签中的代码

<application android:label="ImageCropDemo.Android" android:theme="@style/MainTheme">
    <activity android:name="com.theartofdev.edmodo.cropper.CropImageActivity"
              android:theme="@style/Base.Theme.AppCompat"/>
    <provider android:name="androidx.core.content.FileProvider"
          android:authorities="${applicationId}.fileprovider"
          android:exported="false"
          android:grantUriPermissions="true">
      <meta-data android:name="android.support.FILE_PROVIDER_PATHS"
                       android:resource="@xml/file_paths"></meta-data>
    </provider>
    </application>

另外,你不需要调用CrossMedia.Current.PickPhotoAsync,直接执行ImageCropper,如下代码。

namespace ImageCropDemo
{
    public partial class MainPage : ContentPage
    {
        private MediaFile _mediaFile;
        public MainPage()
        {
            InitializeComponent();

 

            CrossMedia.Current.Initialize();

 

        }
        protected  void OnClickedRectangle(object sender, EventArgs e)
        {
            new ImageCropper()
            {
                //                PageTitle = "Test Title",
                //                AspectRatioX = 1,
                //                AspectRatioY = 1,
                Success = (imageFile) =>
                {
                    Device.BeginInvokeOnMainThread(() =>
                    {
                        image.Source = ImageSource.FromFile(imageFile);
                    });
                }
            }.Show(this);
        }
        async void OpenCamera(object sender, EventArgs args)
        {
            try
            {
                await CrossMedia.Current.Initialize();

 

                //if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
                //{
                //    await DisplayAlert("Alert", "No camera available.", "Ok");
                //    return;
                //}

 

                //_mediaFile = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions
                //{
                //    Directory = "Sample",
                //    Name = "test.jpg",
                //    AllowCropping = true,
                //    PhotoSize = PhotoSize.Medium
                //});

 

                //if (_mediaFile == null)
                //    return;
                //image.Source = ImageSource.FromStream(() =>
                //{
                //    if (Device.OS == TargetPlatform.iOS)
                //    {
                //        return _mediaFile.GetStreamWithImageRotatedForExternalStorage();
                //    }
                //    else
                //    {
                //        return _mediaFile.GetStream();
                //    }
                //});

 

                new ImageCropper()
                {
                    PageTitle = "Test Title",
                    AspectRatioX = 1,
                    AspectRatioY = 1,
                    CropShape = ImageCropper.CropShapeType.Rectangle,
                    SelectSourceTitle = "Select source",
                    TakePhotoTitle = "Take Photo",
                    PhotoLibraryTitle = "Photo Library",
                    Success = (imageFile) =>
                    {
                        Device.BeginInvokeOnMainThread(() =>
                        {
                            image.Source = ImageSource.FromFile(imageFile);
                        });
                    }
                }.Show(this);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("CameraException:>" + ex);
            }
        }
        string imagefile;
        async void OpenGallery(object sender, EventArgs args)
        {
            try
            {
                await CrossMedia.Current.Initialize();

 

                //if (!CrossMedia.Current.IsPickPhotoSupported)
                //{
                //    await DisplayAlert("Alert", "No photos available.", "Ok");
                //    return;
                //}

 

                //_mediaFile = await CrossMedia.Current.PickPhotoAsync(new PickMediaOptions
                //{
                //    PhotoSize = PhotoSize.Medium
                //});

 

                //if (_mediaFile == null)
                //    return;

 

                //image.Source = ImageSource.FromStream(() =>
                //{
                //    return _mediaFile.GetStream();
                //});

 

                new ImageCropper()
                {
                    PageTitle = "Test Title",
                    AspectRatioX = 1,
                    AspectRatioY = 1,
                    CropShape = ImageCropper.CropShapeType.Rectangle,
                    SelectSourceTitle = "Select source",
                    TakePhotoTitle = "Take Photo",
                    PhotoLibraryTitle = "Photo Library",
                    Success = (imageFile) =>
                    {
                        Device.BeginInvokeOnMainThread (() =>
                        {
                            image.Source = ImageSource.FromFile(imageFile);

 

                            imagefile = imageFile;
                        });
                    }
                }.Show(this);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("GalleryException:>" + ex);
            }
        }
    }
}

【讨论】:

  • 能否在mainpage.xaml.cs中添加完整的代码?
  • 张贴。使用插件 ImageCropper 时,您不再需要使用 MediaPlugin,因为 ImageCropper 已经包含它。但是您仍然需要安装并初始化 MediaPlugin。
  • OnClickedRectangle 是一个按钮点击事件。
  • 是否可以将最终图像值设置为MediaFile?因为我需要将所选图像发布到我们的服务器,如下所示:'content.Add(new StreamContent(_mediaFile.GetStream()), "\"file\"", $"\"{_mediaFile.Path}\"") ;'
  • 目前我使用了 _mediaFile.GetStream() 和 {_mediaFile.Path 值。
猜你喜欢
  • 2016-11-19
  • 1970-01-01
  • 2017-01-11
  • 1970-01-01
  • 2020-12-21
  • 2017-06-25
  • 1970-01-01
  • 2014-12-09
  • 1970-01-01
相关资源
最近更新 更多