在 Xamarin.Forms / .NET Standard 體驗之旅 4 的文章中,我們將要來測試每次進行 Xamarin.Forms 實戰課程,大家最想要學習與使用的這個 NuGet 套件:ZXing.Net.Mobile,也就是要開發出具有跨平台的條碼掃描程式。
我們從這個套件在 NuGet 官網上的
內容可以看的出來,這個 NuGet 套件尚未支援 .NET Standard 標準類別庫,而是之前的可攜式 PCL 類別庫,不過,因為 .NET Standard 2.0 類別庫也支援可以使用 PCL 類別庫,因此,我們來測試看看,這個套件可否用於 Prism Template Pack 2.0.7 產生的 Xamarin.Forms 跨平台專案,並且進行一維條碼或者二維條碼 QR Code。
測試範例專案原始碼
開始建立專案
請點選功能表 [檔案] > [新增] > [專案],此時,您會看到底下的 [新增專案] 對話視窗。
我們點選 Prism Template Pack 提供的 Xamarin.Forms 專用的專案樣板,請點選 [已安裝] > [Visual C#] > [Prism] > [Prism Blank App (Xamarin.Forms)]。
接著在名稱欄位輸入該專案名稱後,點選 [確定] 按鈕,以建立此練習專案。
然後,在 [PRISM PROJEC WIZAD] 對話窗中,選擇您要跨平台的作業系統,容器 (Container) 這裡,我個人喜歡與習慣使用 Prism,您可以選擇您自己要用的容器,最後,點選 [CREATE PROJECT] 按鈕。
在這裡,請使用滑鼠右建,點選剛剛建立好的共用類別庫(也就是 .NET Standard 標準類別庫)節點,選擇 [管理方案的 NuGet 套件] 項目。
在 [瀏覽] 標籤頁次上,輸入 ZXing.Net.Mobile
這個關鍵字,搜尋出這個套件。請選擇 ZXing.Net.Mobile.Forms
這個套件,要來安裝到 .NET Standard 專案內。
從下圖中,我們可以看到這個套件並不支援 .NET Standard,不過,我們還是要把這個套件安裝到 .NET Standard 專案內。
當我們點選 [安裝] 按鈕之後,會看到 Visual Studio 會提示您這樣會安裝那些相依性的套件。
修正首頁頁面
我們對於這個應用程式的設計構想是這樣的,當這個應用程式一旦啟動,會在螢幕上顯示一個按鈕,和一些 Label 欄位,這些 Label 欄位是要用來顯示掃描到的條碼資訊。因此,當使用者按下 Scan... 按鈕之後,就會切換到另外一個頁面,這個頁面將會使用 ZXingScannerView 用來進行協助我們做到條碼掃描的工作。
安裝好套件之後,讓我們打開 MainPage.xaml 檔案,修改XAML內容。
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XFQRCode.Views.MainPage"
Title="ZXing.Net.Mobile 條碼掃描">
<StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand">
<Label Text="Welcome to Xamarin Forms and Prism!" />
<Label
Text="條碼類型"/>
<Label
Text="{Binding BarcodeFormatType}"/>
<Label
Text="{Binding BarcodeResult}"/>
<Button
Text="Scan..."
Command="{Binding ScanCommand}"/>
</StackLayout>
</ContentPage>
接著我們打開 MainPageViewModel.cs
檔案,修正 ViewModel 的商業邏輯程式碼。
這裡特別說明的是,當掃描條碼的頁面有掃描到結果,我們是透過頁面導航機制提供的相關事件,進行讀取來自掃描頁面的掃描結果。因此,您可以觀察 OnNavigatingTo 方法,我們將會透過比對 parameters.ContainsKey("Result")
表示式,確認該事件可以讀取掃描結果內容。
namespace XFQRCode.ViewModels
{
public class MainPageViewModel : INotifyPropertyChanged, INavigationAware
{
public event PropertyChangedEventHandler PropertyChanged;
public string BarcodeFormatType { get; set; }
public string BarcodeResult { get; set; }
public DelegateCommand ScanCommand { get; set; }
private readonly INavigationService _navigationService;
public MainPageViewModel(INavigationService navigationService)
{
_navigationService = navigationService;
ScanCommand = new DelegateCommand(() =>
{
_navigationService.NavigateAsync("ScanPage");
});
}
public void OnNavigatedFrom(NavigationParameters parameters)
{
}
public void OnNavigatingTo(NavigationParameters parameters)
{
if(parameters.ContainsKey("Result"))
{
var fooReslut = parameters["Result"] as Result;
BarcodeFormatType = fooReslut.BarcodeFormat.ToString();
BarcodeResult = fooReslut.Text;
}
}
public void OnNavigatedTo(NavigationParameters parameters)
{
}
}
}
新增條碼頁面
接下來,我們需要新建立一個頁面,ScanPage,我們將會在這個頁面上使用 ZXingScannerView 用來進行協助我們做到條碼掃描的工作。
當新增完成 ScanPage 頁面,讓我們打開 ScanPage.xaml 檔案,修改XAML內容。
首先我們先宣告一個新的命名空間,xmlns:Zxing="clr-namespace:ZXing.Net.Mobile.Forms;assembly=ZXing.Net.Mobile.Forms"
,這樣,我們就可以使用這個命名空間前置詞參考到這個 ZXingScannerView 控制項。
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
xmlns:Zxing="clr-namespace:ZXing.Net.Mobile.Forms;assembly=ZXing.Net.Mobile.Forms"
prism:ViewModelLocator.AutowireViewModel="True"
x:Class="XFQRCode.Views.ScanPage"
Title="進行條碼掃描中..."
>
<Grid
>
<Zxing:ZXingScannerView
HorizontalOptions="Fill"
IsAnalyzing="{Binding IsAnalyzing}"
IsScanning="{Binding IsScanning}"
Result="{Binding ScanResult, Mode=TwoWay}"
ScanResultCommand="{Binding ScanResultCommand}"
/>
<Zxing:ZXingDefaultOverlay Opacity="0.9" ShowFlashButton="False" />
</Grid>
</ContentPage>
接著我們打開 ScanPageViewModel.cs
檔案,修正 ViewModel 的商業邏輯程式碼。
一旦條碼有掃描到之後,將會執行 ScanResultCommand 的委派方法,不過,您需要特別注意,我們需要使用 Device.BeginInvokeOnMainThread
方法,將您要執行的程式碼,全部都指定在 UI (Main) Thread 上運行。
namespace XFQRCode.ViewModels
{
public class ScanPageViewModel : INotifyPropertyChanged, INavigationAware
{
public event PropertyChangedEventHandler PropertyChanged;
public bool IsAnalyzing { get; set; } = true;
public bool IsScanning { get; set; } = true;
public Result ScanResult { get; set; }
private readonly INavigationService _navigationService;
public DelegateCommand ScanResultCommand { get; set; }
public ScanPageViewModel(INavigationService navigationService)
{
_navigationService = navigationService;
ScanResultCommand = new DelegateCommand(async () =>
{
Device.BeginInvokeOnMainThread(async () =>
{
IsAnalyzing = false;
IsScanning = false;
var fooPara = new NavigationParameters();
fooPara.Add("Result", ScanResult);
// 回到上頁,並且把掃描結果帶回去
await _navigationService.GoBackAsync(fooPara);
});
});
}
public void OnNavigatedFrom(NavigationParameters parameters)
{
}
public void OnNavigatingTo(NavigationParameters parameters)
{
}
public void OnNavigatedTo(NavigationParameters parameters)
{
}
}
}
進行測試
最後,設定預設起始專案為 Android 專案,並且需要使用實體手機來進行測試。