少し大きくなりすぎたアプリケーションの開発者が直面する問題の1つは、画面間のナビゲーションです。 スクリプトが非線形になった場合、標準のstartActivityとchangeFragmentを使用して取得することはすでに困難です。 一人一人がこの問題を独自の方法で解決しました:彼はナビゲーションについて独自の決定を下し、サードパーティ(たとえばCicerone )を使用しました。 これは本当にGoogleエンジニアを混乱させ、現在はGoogle I / O 2018にナビゲーションソリューションが登場しました。
この記事では、ナビゲーションのフレームワークに一般的に必要なものを理解し、Googleのソリューションがどのように配置され、どのような抽象化が機能するかを理解します。
ナビゲーション要件
ナビゲーションフレームワークに設定した要件から始めましょう。 一連の記事では、それらが実装されているかどうかに気付いたときにそれらに戻ります。
優先度1 (必須):
[1]ライフサイクルからの分離。
[2]ネストされたナビゲーションを実行する機能。
[3]「戻る」コマンドで前の画面を自動的に開きます。
[4]アニメーションを追加して画面を変更することができます。
[5]引数を渡す。
[6]ランタイムナビゲーションを再構築する機能。
[7]共有要素のサポート。
[8]一連の画面を開閉する機能。
優先度2 (望ましい):
[9]ディープリンクを操作するための便利なメカニズム。
[10]アクティビティ、フラグメント、ビューでの実装の可能性。
[11]ナビゲーションのテスト。
[12]変更の柔軟性。
[13]ビジネスロジックからナビゲートする機能。
[14]ナビゲーションスタックにある画面を置き換える機能。
[15]コンパイル時に引数をチェックします。
[16]シンプルなデザインのための視覚的表現があります。
ナビゲーションの仮定
そのため、最初に、Googleが指示する新しい原則に対処します。
原則1. 開始点を修正
アプリケーション内のすべてのリンクは1つのポイントにつながります。つまり、常に1つの画面(本質的にはSplashScreen)から開始し、アプリケーションのどこに移動するかを決定します。
原則2。 ナビゲーションはLIFOスタックとして機能します
プッシュとポップの操作のみを行うことができ、スタックの中央にある画面は操作できません。
原則3. [ 戻る]ボタンと[上へ]ボタンは同じように機能します
最後に、ツールバーの矢印とハードバックの矢印は同じように機能します。 これ以上混乱するユーザーはいません!
原則4. アプリケーションのディープリンクは、自分で画面に到達した場合と同様に、画面のスタックを生成します
「戻る」ボタンをクリックしてディープリンクを使用してアプリケーションを開くと、ディープリンクなしで開いた場合と同じように、すべての画面が表示されます。
定義
クイックダイビングのために、 Githubからサンプルをダウンロードして、実際のすべてを途中で見ることができます。
記事の最後には、Android Studioがすぐに起動しなかった場合にAndroid Studioを克服する方法も記載されています。
では、新しいナビゲーションフレームワークはどのように機能しますか? 次のコンポーネントで構成されています。
目的地 -ナビゲートすると開く画面。 ドキュメントを便利に参照できるように、この指定を保持しています。 Fragment 、 Activity 、 Viewのほか 、一般的にナビゲーション画面で意味するすべてのものを指定できます。 将来、フラグメントについて話しますが、フラグメントだけでなく使用できることを忘れないでください。
NavHostインターフェースは、ユーザーがアプリケーションをナビゲートするときに画面( Destination )が切り替わるビューコンテナーです。 デフォルトの実装はNavHostFragmentです。 ナビゲーション用にxmlが設定されています。
NavGraphはxmlナビゲーション送信です。 宛先画面とそれらの間の接続について説明します。
NavControllerは、ナビゲーションメカニズムを実装するエンティティです。 画面を切り替えるときに方向を変えるのは彼にとってです( Destination )。 NavControllerはNavHostにインストールされます 。 既製のNavHostFragmentを扱っている場合は、 NavControllerを作成して提供するためのすべてのロジックがすでに行われています。
アクション -別の画面に切り替えるコマンド。 宛先を変更するためにNavControllerに送信します
FragmentNavigator-フラグメントトランザクション自体をカプセル化する内部クラス。
動作原理
構築されたNavGraphはNavHostFragmentに設定されます ( NavHostの特殊なケースとして)。 これで、 アクションとは何か、それらに対応する画面がわかりました。
NavHostFragmentは、今後のトランザクションを通知するNavControllerを提供します。 目的のアクションコマンドを発行して、コードからNavControllerにアクセスします 。 NavHostFragmentが対話するFragmentNavigatorは、最終的な画面切り替えを担当します。
実装
この獣を扱う方法を理解する時が来ました。
まず、必要なすべてのライブラリとプラグインを接続します。 Googleの適切なセクションで関連情報を確認してください。
buildscript { ext.kotlin_version = '1.2.41' repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.2.0-alpha14' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } }
dependencies { def nav_version = '1.0.0-alpha01' implementation "android.arch.navigation:navigation-fragment:$nav_version" implementation "android.arch.navigation:navigation-ui:$nav_version" // }
ナビゲーショングラフを作成する
次に、ナビゲーションマップを作成します。 別のリソースタイプが修正されました- ナビゲーション 、特別なエディターが提供されています。
これを行うには、内容を含むファイルres / navigation / nav_graph.xmlを作成します。 これは手ではなく、 標準のコンストラクターを介して行うことができます
<?xml version="1.0" encoding="utf-8"?> <navigation xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> </navigation>
エディターを「 設計」タブに切り替え、その中に画面( Destination )を取り込み、 アクション矢印を使用してそれらを接続します。
仕組みは非常に直感的で、ConstraintLayoutとのやり取りに似ています。 問題がある場合は、Googleの詳細なガイドをご覧ください。 (要件[3]は満たされています)。
コンストラクターは、 宛先 (画面)とアクション (矢印)の2種類のエンティティで構成されています。
宛先には一連の属性があります。
- ID-アクションを通じて他の人と通信するための画面識別子。
- クラス -この画面のクラス(たとえば、LoginFragment)。
さらに、パラメータの3つのグループがあります。 - 引数は、パラメータ化する引数です。
- アクション -現在の画面からどこへ行くかを決定するコマンド。
- ディープリンク -アプリケーションの外部から画面に移動するためのディップリンク。
この画面を開始画面にすることもできます。
アクションには一連の属性があります。
- ID-アクション識別子:画面を切り替えるために使用します。
- 宛先 -アクションが導く宛先 ID。
さらに、パラメーターの4つのグループがあります。 - 遷移 -切り替えのアニメーション。 アクションのさまざまなタイプを指定できます:Enter、Exit、Pop Enter、Pop Exit。 アニメーションはxmlリソースから取得されます。 独自に定義するのは簡単です。適切なリソースをres / animフォルダーに追加するだけです。 (nav_custom_enter_anim.xmlの例を参照)
- ArgumentDefaultValue-デフォルトでフラグメントの引数の値。
- PopBehavior-フラグメントを閉じたときのナビゲーションの動作。 たとえば、スタックのすべての画面を閉じて、開始画面に戻ることができます。 (Action action_notificationFragment_to_dashboardFragmentの例を参照してください-メイン画面に移動します)。 (満たされた要件[16])
- LaunchOption-スタックを操作するためのオプション。アクティビティスタックを操作するときの起動モードを連想させます。
結果は、記事のタイトルに似た画像です。
ナビゲーショングラフをコンテナにバインドします
ナビゲーショングラフがあります。これをコンテナにバインドします。 これを行うには、 NavHostFragmentナビゲーション全体のホルダーとして機能するMainActivityをxmlに追加し、 属性を設定します 。
<?xml version="1.0" encoding="utf-8"?> <FrameLayout android:id="@+id/container" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <fragment android:id="@+id/nav_host_fragment" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="match_parent" android:layout_height="match_parent" app:navGraph="@navigation/nav_graph" app:defaultNavHost="true" /> </FrameLayout>
最後から2番目の行は、作成したナビゲーショングラフに従ってナビゲーションが実行されることを示しています。
最後の行は、 NavHostFragmentがデフォルトに設定されていることを意味します。これにより、システムの「戻る」処理が保証されます。 ナビゲーションの原則3を満たすために、 Activityの戻る矢印のアクションを再定義する必要もあります。
override fun onSupportNavigateUp() = findNavController(R.id.nav_host_fragment).navigateUp()
ナビゲーションコマンドの実行
別のフラグメントに切り替えるには、Navigatorを取得する必要があります。
これにはいくつかの方法があります。
NavHostFragment.findNavController(Fragment) Navigation.findNavController(View) Navigation.findNavController(Activity, @IdRes int viewId)
実際、これらはNavHostを実装するビューを検索し、 そこからNavControllerを取得するためのさまざまなコンテキストからのコマンドです。
次に、ナビゲーションのメソッドの1つが、結果のNavControllerで呼び出されます。
fragment_home_button_dashboard.setOnClickListener { activity?.let { findNavController(it, R.id.nav_host_fragment) .navigate(R.id.action_homeFragment_to_dashboardFragment) } }
NavControllerを使用してナビゲートするには
私たちは自由に使える:
- オーバーロードされたいくつかのメソッドnavigate() 。 それらのパラメーターは
- ActionId-xmlからの同じアクションID
- バンドル-引数のセット
- NavOptions-アニメーション、スタックなどを決定するActionの引数、
- NavDirections-バンドルとActionIdをラップする抽象化
- 現在のスタックから画面にジャンプするためのオーバーロードされたpopBackStack()メソッドのカップル。
この例では、 アクションのみが使用されて先に進みます。 「戻る」コマンドは自動的に処理され、 アクションの反対のアクションを引き起こします(同じPopBehavior属性)
そのため、 DashboardFragment画面からAction (コマンド) action_notificationFragment_to_dashboardFragmentの後に戻ると、 NotificationFragmentではなくHomeFragmentに到達します。
<action android:id="@+id/action_notificationFragment_to_dashboardFragment" app:destination="@id/dashboardFragment" app:enterAnim="@anim/nav_custom_enter_anim" app:popUpTo="@+id/homeFragment" />
まとめ
一見したところ、Googleのフレームワークは鋭い非難を引き起こさず、より詳細に検討する必要があるように見えます。
このパートでは、[3]と[16]の要件が満たされていることを確認しました。 一見すると、Googleのソリューションのナビゲーション要件の表は次のようになります。
優先度1 (必須):
[1]ライフサイクルからの分離。
[2]ネストされたナビゲーションを実行する機能。
[3]「戻る」コマンドで前の画面を自動的に開きます [✓]。
[4]アニメーションを追加して画面を変更することができます。
[5]引数を渡す。
[6]ランタイムナビゲーションを再構築する機能。
[7]共有要素のサポート。
[8]一連の画面を開閉する機能。
優先度2 (望ましい):
[9]ディープリンクを操作するための便利なメカニズム。
[10]アクティビティ、フラグメント、ビューでの実装の可能性。
[11]ナビゲーションのテスト。
[12]変更の柔軟性。
[13]ビジネスロジックからナビゲートする機能。
[14]ナビゲーションスタックにある画面を置き換える機能。
[15]コンパイル時に引数をチェックします。
[16]シンプルなデザインの視覚的表現があります [✓]。
次は?
次の部分で検討します(順序が変わる可能性があります)。
- 引数付きのフラグメントを開くトランザクション。
- ディープリンク。
- BottomNavigationおよびツールバーを操作するための組み込みツール。
- さまざまな種類のナビゲーション:ネストされたアクティビティと複数のアクティビティ。
- 内部ですべてがどのように配置され、ライフサイクルでどのように機能するか。
- ビューナビゲーションを作成する方法。
- コードからナビゲーショングラフを組み立てる方法。
- ナビゲーションをテストする方法。
- これらすべてが戦いの準備ができているか、どのような抽象化を追加する必要があります。
今すぐ始める方法
説明した例は、私のGithubにあります。 実行するには、少なくとも3.2 CanaryのAndroid Studioが必要です。
ビルドツール28.0.0-rc1のSDKバージョンでのみ始めました(28.0.0-rc2では、すべてが無限にダウンロードされました)
突然これが役に立たない場合は、きれいにしてください-私はいくつかのケースで助けられました。