App 通常需要與遠端伺服器進行資料的交換,在這交換的過程中,由於網路的因素,可能需要花費一定的等待時間,換句話說使用者需要等待資料的取得及載入,因此一個設計較好的App通常會適當的給予一些訊息或 UI 效果,讓使用者了解目前正在處理資料的取得,減少使用者心理的焦慮感。Xamarin.Forms 提供了ActivityIndicator 控制項,讓我們可以很容易的做到加載 Loading 的UI設計,並且是可以轉化為各個平台不同的 Loading 效果。
使用 ActivityIndicator 本身並不難,只需要設置 IsRunning=true 就可以在 UI 上顯示 loading 效果,不過實務上一個頁面在操作上除了資料加載之外,可能還有很多時刻也是會需要顯示 loading 效果的,例如圖片的載入,資料的排序,或是其它可能引起時間等待的操作,所以如果一直在程式碼邏輯裡不斷的到處控制IsRunning=true 或IsRunning=false,也許不是個好選擇,接下來的範例裡,將透過 Binding IsRunning 屬性的手法,搭配 Model 自定義 IsBusy 屬性,來實作 Loading 設計。
首先在 Xaml 裡安排了一顆 Button 及 ActivityIndicator 控制項,並且設置 IsRunning 的屬性值綁定 IsBusy(稍後會看到這是我們 ViewModel 類別所公開出來的屬性)
<StackLayout Orientation="Vertical">
<StackLayout>
<Button Text="Get Data!!" x:Name="BtnGetData"
VerticalOptions="Start"
HorizontalOptions="Center"></Button>
</StackLayout>
<StackLayout>
<ActivityIndicator x:Name="Loading" IsRunning="{Binding IsBusy}"
HorizontalOptions="Center"
VerticalOptions="Center"
Color="Black"/>
</StackLayout>
</StackLayout>
接著在專案裡建立一個 ActivityIndicatorViewModel 類別做為 ViewModel
public class ActivityIndicatorViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private bool _isBusy;
public bool IsBusy
{
get
{
return _isBusy;
}
set
{
_isBusy = value;
PropertyChanged(this,new PropertyChangedEventArgs("IsBusy"));
}
}
}
- 在這個類別裡提供了 IsBusy 的公開屬性(後面程式會拿來運用)
- 實作INotifyPropertyChanged介面,當屬性值發生變動時,以便通知UI進行更新
回到頁面程式碼的部份,我們讓這個 ActivityIndicatorViewModel 作為頁面的 BindingContext 來源,並且讓 ActivityIndicator 控制項繫結 ActivityIndicatorViewModel 的 IsBusy 屬性,就可以利用ViewModel的屬性值變化來控制 UI 是否要顯示Loading 效果,為了示範方便,在 Button 事件裡採用了 Task.Delay 來模擬延遲效果。
private ActivityIndicatorViewModel ViewModel { get; set; }
public MainPage()
{
InitializeComponent();
ViewModel = new ActivityIndicatorViewModel();
BindingContext = ViewModel;
this.BtnGetData.Clicked += async (sender, args) => await GetDataTaskAsync();
}
private async Task GetDataTaskAsync()
{
ViewModel.IsBusy = true;
await Task.Delay(3000);
ViewModel.IsBusy = false;
}
簡單來說,整個機制上是ViewModel實作INotifyPropertyChanged介面,並同公開IsBusy屬性,而 ActivityIndicator UI 控制項設置 IsRunning 的屬性值綁定 IsBusy,因此只要 ViewModel 的IsBusy屬性值有了改變,就會因為實作了 INotifyPropertyChanged 介面,所以 UI 上也會同時做相對的改變。
完整Demo專案:https://github.com/iangithub/Xamarin-Forms-HoL/tree/master/XAppActivityIndicator
By No.18