Xamarin.Forms IsBusyプロパティの活用
はじめに
Xamarin.Formsをお楽しみの皆様、いかがお過ごしでしょうか。
Pageクラスに存在しているのに割と使われる事が少ないプロパティ「IsBusy」
このプロパティがTrueの時に
iOSではなんか画面の上の方で微妙にクルクル回って
Androidでは微妙な大きさのIndicatorが回ったり回らなかったり
まあ多分あんまり利用している人多くないんじゃないかなぁとか勝手に思っております。
でもせっかくプロパティがあるんだから活かしたい。という事で
今回はAndroidのNavigationPageをカスタマイズしてちょっとかっこいい気がするIsBusy表現を作ってみたいと思います。
完成形
コード
解説
コードを見るとわかる通り、実はそんなに大したことはしていないです。
AndroidのNavigationPageRendererを継承したMyNavigationPageRendererを作成しています。
ポイントとしては3点。
- 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; }
- 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); } }
- 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