[ Xamarin ] ActivityIndicator 透過 Binding IsRunning 屬性實現 Loading 設計

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