読者です 読者をやめる 読者になる 読者になる

Makopy'5 La6

スマホアプリ開発とかその周辺のこととか関係ないこと。または恋は言ってみりゃボディー・ブロー

(Xamarin.Forms)Hierarchical Navigation

Xamarin.Forms

前回のお話。
makopy5la6.hatenadiary.jp

画面遷移のことを書きましたが。
特に理解しておくべき画面遷移として、下記を挙げました。

  • Hierarchical Navigation
  • Modal Pages
  • TabbedPage

今回はHierarchical Navigationにスポットを当ててみたいと思います。

Hierarchical Navigationのポイント

兎にも角にも、まずはベーシックな知識は公式のDevelopersガイドから得るのが一番です。
Hierarchical Navigation - Xamarin

画面遷移の管理

  • NavigationStackで管理
  • NavigationStackのRootはNavigationPageとする
  • 次の画面に行くときはNavigationStackにPush
    • Navigation.PushAsync
  • 前の画面に戻るときはNavigationStackからPop
    • Navigation.PushAsync
  • Root画面までPopできる
    • Navigation.PopToRootAsync

NavigationStackの操作

  • NavigationStack内に画面を挿入
    • Navigation.InsertPageBefore
  • NavigationStack内から画面を削除
    • Navigation.RemovePage

あくまで私感でしかありませんが…。
この手の操作はあまり好きになれません。
PopToRootAsyncも含めて、Pop/Push以外の処理を書かねばならない場合、
「そもそも画面遷移仕様がきちんと整理されているのか?」
「仕様はともかく、実装面で他の方法はないのか?」
という風に疑うべきだと思います。

またこの様な場合、
「特定の条件やシーンに応じて画面遷移に変更を加えたい」
というようなパターンが多いと思いますが、仕様面の都合はNavigationStackでは管理してもらえません。
なるべくベーシックで自然な画面遷移に収めた方が安心です。

とは言え…。
「事実は小説より奇なり」
本番の開発では諸般の都合でトリッキーな画面遷移を書かざるを得ない時があるワケです。
こういう特殊な操作があることは覚えておいて、やむを得ない時は十分注意して使うというくらいのスタンスを取りたいと思います。

NavigationStackの取得

Page内でなら、下記の様に取得できます。

PageのList(ReadOnly)が取得できます。
NavigationStack - Xamarin

ReadOnlyなので、直接NavigationStackの操作ができるわけではありませんが。
ログ出ししたり、操作メソッドの引数に設定するPageを取得したりという用途で使えると思います。

UI関連

  • 基本的にNavigationBarを伴う
  • NavigationBarのTitleにはPageのTitleが採用される
    • 基本的にはこのTitleが次の画面の戻るボタンのTitleになる
    • Pageのタイトル

画面のライフサイクル

画面遷移に伴わせて、どんなライフサイクルメソッドが呼ばれるかを検証したかったのですが…。
Xamarin.Formsの画面ライフサイクルって…

  • OnAppearing
  • OnDisappearing

の2つしかなくて、 基本的には画面の表示/非表示しか捕捉できません。

Hierarchical Navigationと画面ライフサイクル

下記のサンプルコードで確認してみました(iOS/Android)

github.com

動作確認用のどうしようもないコードですが…。

  • TopPage→Page1→Page2→Page3とPushAsync
  • Page3→Page2→Page1→TopPageとPopAsync
  • Page3からはPopToRootAsync, InsertPageBefore, RemovePageも試しています。
  • 各画面のOnAppearingOnDisappearing でログ出力

確認まとめ

iOSAndroidで同じ結果

  • PushAsync, PopAsync
    • 遷移元画面のOnDisappearing → 遷移先画面のOnAppearing
  • PopToRootAsync
    • 遷移元画面のOnDisappearing → 遷移先画面のOnAppearing
  • InsertPageBefore
    • ライフサイクルメソッドは呼ばれない
  • RemovePage
    • ライフサイクルメソッドは呼ばれない

当然ながら、画面の表示/非表示が発生しなければ、OnAppearingOnDisappearingは呼ばれない。

おまけの確認

iOSAndroidで同じ結果

各画面のOnAppearingOnDisappearingのタイミングで、併せてNavigationStackの中身をログ出力していたのですが…。

  • PopToRootAsyncした場合、NavigationStackが一度空になってからTopPageが積まれる
  Page3.xaml.cs - OnDisappearing
  ***** NavigationStack *****

  TopPage.xaml.cs - OnAppearing
  ***** NavigationStack *****
  HierarchicalNavigationSample.TopPage