眠いしお腹すいたし(´・ω・`)

C#関連を主に書きます。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

Xamarin.Forms IsBusyプロパティの活用

はじめに

Xamarin.Formsをお楽しみの皆様、いかがお過ごしでしょうか。

Pageクラスに存在しているのに割と使われる事が少ないプロパティ「IsBusy」

このプロパティがTrueの時に

iOSではなんか画面の上の方で微妙にクルクル回って

Androidでは微妙な大きさのIndicatorが回ったり回らなかったり

まあ多分あんまり利用している人多くないんじゃないかなぁとか勝手に思っております。

でもせっかくプロパティがあるんだから活かしたい。という事で

今回はAndroidのNavigationPageをカスタマイズしてちょっとかっこいい気がするIsBusy表現を作ってみたいと思います。

完成形

https://media.giphy.com/media/3o7btRdJFJMn0Nd4Dm/giphy.gif

コード

gist.github.com

解説

コードを見るとわかる通り、実はそんなに大したことはしていないです。

AndroidのNavigationPageRendererを継承したMyNavigationPageRendererを作成しています。

ポイントとしては3点。

  1. OnElementChangedをoverrideしてAndroidのProgressBarというViewを作成しAddViewでNavagationPageの子要素に追加する。

 AndroidのNavigationPageはToolbarとPageContainerという二つのViewで構成されているのですが、そこにProgressBarを追加する感じです。

if (_progress == null) {
    _progress = new AProgressBar(Context, null, Android.Resource.Attribute.ProgressBarStyleHorizontal)
    {
     Indeterminate = true
    }; 
    AddView(_progress);
    _progress.Visibility = ViewStates.Invisible;
}
  1. OnLayoutをoverrideして表示位置と大きさを決める。

OnLayoutのタイミングでProgressBarのレイアウトを設定します。 またこのタイミングで重なり順も指定してしまいます。 今回はToolBarのすぐしたくらいに配置しました。

for (var i = 0; i < ChildCount; ++i) {
    var view = GetChildAt(i);
    if (view is Toolbar) {
        _progress?.SetZ(view.GetZ() + 1);
        _progress?.Layout(l, view.Bottom - 10, r, view.Bottom + 10);
    }
}
  1. OnElementPropertyChangedをoverrideしてIsBusy変更時にProgressBarのVisibilityを変更して表示非表示を切り替える。
if (e.PropertyName == nameof(Element.IsBusy)) {
    var page = (NavigationPage) sender;
    _progress.Visibility = page.IsBusy ? ViewStates.Visible : ViewStates.Invisible;
}

あとは子ページのIsBusyに同期させたりしていますがしなくても良いかと思います。

どうでしょう?

たったこれだけで、なんかちょっとかっこいい気がしないでもないLoadingが作れちゃいます。

IsBusyのカスタム動作をCustomRendererで実装する利点としては必要なくなったらExportRenderer外しちゃえばよくてXamlとかViewModelに影響を与えずに切り替えられるっていう点が良いですね。

今回はこれまでです。

ではでは(〃^∇^)o