web-dev-qa-db-ja.com

Android複数スタックのJetPackナビゲーション

Jetpack Navigationを使用していますversion 1.0.0-alpha04下部ナビゲーション付き。動作しますが、ナビゲーションが正しく行われません。たとえば、タブAとタブBがあり、タブAIからページCに移動し、そこからタブBに戻って再びタブAに戻る場合、ページCではなく、タブAにルートフラグメントが表示されます。私が期待するものではありません。

タブごとに異なるスタックを持つソリューションを探しているので、戻ったときに各タブの状態が予約されています。また、このフラグメントがすべて不良であるため、メモリにこのフラグメントをすべて保持したくないパフォーマンスへの影響、ジェットパックナビゲーションの前に、私はこのライブラリを使用しました https://github.com/ncapdevi/FragNav 、それはまさに何をするか、今私はジェットパックナビゲーションで同じものを探しています。

8

EDIT 2:ファーストクラスのサポートはまだありませんが(これを書いている時点では)、Googleはサンプルを更新し、これがどうあるべきかという例を示しました現時点では解決済み: https://github.com/googlesamples/Android-architecture-components/tree/master/NavigationAdvancedSample


主な理由は、アプリのバックスタック全体を保持するためにNavHostFragmentを1つだけ使用することです。

解決策は、各タブが独自のバックスタックを保持することです。

  • メインレイアウトで、各タブフラグメントをFrameLayoutで囲みます。
  • 各タブフラグメントはNavHostFragmentであり、各タブフラグメントに独自のバックスタックを持たせるために、独自のナビゲーショングラフが含まれています。
  • _BottomNavigationView.OnNavigationItemSelectedListener_をBottomNavigtionViewに追加して、各FrameLayoutの可視性を処理します。

これはまた、「...このすべてのフラグメントをメモリに保持したくない...」も処理します。これは、デフォルトでNavHostFragmentによるナビゲーションがfragmentTransaction.replace()を使用するためです。には、常にNavHostFragmentsと同じ数のフラグメントしかありません。残りは、ナビゲーショングラフのバックスタックにあります。

編集:Googleはネイティブ実装に取り​​組んでいます https://issuetracker.google.com/issues/80029773#comment25


詳細

BottomNavigationViewに2つのメニュー選択肢、DogsCatsがあるとします。

_<menu xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <item Android:id="@+id/dogMenu"
        .../>

    <item Android:id="@+id/catMenu"
        .../>
</menu>
_

次に、2つのナビゲーショングラフ、たとえば_dog_navigation_graph.xml_および_cat_navigation_graph.xml_が必要です。

_dog_navigation_graph_は次のようになります

_<navigation
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:id="@+id/dog_navigation_graph"
    app:startDestination="@id/dogMenu">
</navigation>
_

および対応する_cat_navigation_graph_。

_activity_main.xml_に2を追加しますNavHostFragments

_<FrameLayout
    Android:id="@+id/frame_dog"
    ...>

    <fragment
        Android:id="@+id/dog_navigation_Host_fragment"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:name="androidx.navigation.fragment.NavHostFragment"
        app:navGraph="@navigation/dog_navigation_graph"
        app:defaultNavHost="true"/>
</FrameLayout>
_

そしてその下にあなたの猫に対応するNavHostFragmentを追加します。猫のフレームレイアウトで_Android:visibility="invisible"_を設定します

さて、MainActivityonCreateViewでは、

_bottom_navigation_view.setOnNavigationItemSelectedListener { item ->
    when (item.itemId) {
        R.id.dogMenu -> showHostView(Host = 0)
        R.id.catMenu -> showHostView(Host = 1)
    }
    return@setOnNavigationItemSelectedListener true
}
_

showHostView()が行っていることは、FrameLayoutsをラップしているNavHostFragmentsの可視性を切り替えることです。したがって、それらを何らかの方法で保存してください。 onCreateView

_val hostViews = arrayListOf<FrameLayout>()  // Member variable of MainActivity
hostViews.apply {
    add(findViewById(R.id.frame_dog))
    add(findViewById(R.id.frame_cat))
}
_

これで、どのhostViewsを表示するか非表示にするかを簡単に切り替えることができます。

11
Algar