在上一篇博文《[UWP]如何實現UWP平臺最佳圖片裁剪控件》中我講解了編寫ImageCropper控件的過程及知識分享。在那篇文章裏,我大言不慚的稱其爲UWP平臺最佳圖片裁剪控件(主要是沒有別的相似控件來充當對手🤣)。其實寫博客時的那個版本連交互動畫都尚未,遠遠稱不上「最佳」。html
不過,這一個月來ImageCropper通過數次迭代,它已經具備很是棒的體驗了!另外還有一件使人興奮的事,它即將加入WindowsCommunityToolkit中(PR已經接近尾聲)!這將讓更多UWP開發者能夠體驗它。git
今天這篇博文我來說下ImageCropper的一個特殊應用實例。github
先來思考一下這個問題:express
若是咱們的應用只有一個界面須要調用圖片剪裁,那很好,直接在這個頁面嵌入ImageCropper控件就能夠輕鬆完成了。可是,若是這個應用有多處須要裁剪圖片的地方(譬如說上傳圖片、修剪照片、裁剪頭像...),咱們是否能夠爲這些須要裁剪圖片的地方構建一個公共的可調用組件呢?windows
事實上,咱們能夠藉助HHChaosToolkit中的Picker組件來完成這一想法。框架
以前我寫過一系列關於Picker的文章,不瞭解Picker的話建議能夠抽時間閱讀:async
那麼,咱們今天使用Picker和ImageCropper來爲應用構建一個公共裁剪組件。ide
先看下效果圖:佈局
如何實現的呢?動畫
建立一個空白UWP應用項目,並引入了HHChaosToolkit.UWP以及ImageCropper.UWP這兩個Nuget包。
我在HHChaosToolkit項目首頁寫過:
HHChaosToolkit是一套適用於MVVM框架下使用的彈窗層組件庫。
HHChaosToolkit其中包含了Picker彈窗組件、SubWindows子窗口組件以及輕量級MVVM框架。咱們在這個例子中使用到的是它的Picker以及MVVM部分。
ImageCropper則是這個例子中主要依賴的功能組件。
項目結構以下圖:
其中包含了兩個頁面,ImageCropperPickerPage
便是這個例子中咱們要構建的圖片公共裁剪組件,MainPage
中包含了調用使用公共裁剪組件的示例,邏輯代碼均在其對應的ViewModel中。
ImageCropperPicker就是咱們想要的圖片公共裁剪組件的Picker實現,它能夠在任意地方調用(不管是在View仍是ViewModel的代碼中),且不會中斷當前的操做,其調用原理能夠查看我以前的博文《[UWP]使用Popup構建UWP Picker》。
這個頁面中包含了ImageCropper控件,用於實現圖片裁剪功能。
界面佈局以下:
<Page x:Class="ImageCropperPicker.Views.ImageCropperPickerPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:cropper="using:ImageCropper.UWP" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="using:ImageCropperPicker.Views" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" DataContext="{Binding ImageCropperPickerViewModel, Source={StaticResource Locator}}" RequestedTheme="Dark" mc:Ignorable="d"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <cropper:ImageCropper x:Name="ImageCropper" Padding="80" AspectRatio="{Binding AspectRatio}" Background="Transparent" CircularCrop="{Binding CircularCrop}" Mask="#af000000" SourceImage="{Binding SourceImage}" /> <Grid Grid.Column="1" Background="#af000000"> <StackPanel Padding="55" VerticalAlignment="Center"> <AppBarButton Margin="0,15" Click="Button_Click" Icon="Accept" Label="OK" /> <AppBarButton Command="{Binding ExitCommand}" Foreground="White" Icon="Cancel" Label="Cancel" /> </StackPanel> </Grid> </Grid> </Page>
邏輯層代碼中,我使用ImageCropperConfig
類來接受調用方傳來的參數,並在打開Picker時讀取參數,初始化Picker。
ImageCropperConfig定義以下:
public class ImageCropperConfig { public StorageFile ImageFile { get; set; } public double AspectRatio { get; set; } = -1; public bool CircularCrop { get; set; } }
ImageCropperPicker的ViewModel代碼:
using HHChaosToolkit.UWP.Mvvm; using ImageCropperPicker.Models; using System; using Windows.UI.Xaml.Media.Imaging; using Windows.UI.Xaml.Navigation; namespace ImageCropperPicker.ViewModels { public class ImageCropperPickerViewModel : ObjectPickerBase<WriteableBitmap> { private WriteableBitmap _sourceImage; public WriteableBitmap SourceImage { get => _sourceImage; set => Set(ref _sourceImage, value); } private double _aspectRatio; public double AspectRatio { get => _aspectRatio; set => Set(ref _aspectRatio, value); } private bool _circularCrop; public bool CircularCrop { get => _circularCrop; set => Set(ref _circularCrop, value); } public async override void OnNavigatedTo(NavigationEventArgs e) { if (e.Parameter is ImageCropperConfig config) { var writeableBitmap = new WriteableBitmap(1, 1); using (var stream = await config.ImageFile.OpenReadAsync()) { await writeableBitmap.SetSourceAsync(stream); } SourceImage = writeableBitmap; AspectRatio = config.AspectRatio; CircularCrop = config.CircularCrop; } base.OnNavigatedTo(e); } } }
在這裏,完成裁剪圖片的操做我放在了界面上OK按鍵的後臺代碼中(實際上仍是調用的Picker中的方法):
private async void Button_Click(object sender, RoutedEventArgs e) { var img = await ImageCropper.GetCroppedBitmapAsync(); ViewModel?.SetResult(img); }
調用方法很是的簡單,直接使用HHChaosToolkit中的ObjectPickerService
來啓動Picker,而且等待Picker返回結果便可。
比較特別的是,在這裏我經過使用PickerOpenOption
讓裁剪圖片Picker能夠覆蓋到整個應用界面,UI表現看起來更佳。
調用代碼:
private async Task<ImageSource> CropImage(ImageCropperConfig config) { var startOption = new PickerOpenOption { VerticalAlignment = VerticalAlignment.Stretch, HorizontalAlignment = HorizontalAlignment.Stretch, }; var ret = await ViewModelLocator.Current.ObjectPickerService.PickSingleObjectAsync<WriteableBitmap>( typeof(ImageCropperPickerViewModel).FullName, config, startOption); if (!ret.Canceled) { return ret.Result; } return null; }
是否是看起來很簡單?是的,優雅的調用方式就應該這麼簡單!
正如我以前所說,Picker組件在不少地方均可以派上用處,咱們幾乎能夠用它來實現一切UWP自定義彈出框,很是歡迎有相似需求的開發者們試用!
這個示例項目開源在Github中,感興趣的能夠自行Clone編譯,同時項目中的代碼請隨意享用,喜歡的話請不要忘記Star!
本篇博客到此結束!謝謝你們閱讀!