折りたたみ型のナビゲーション

折りたたみ型ナビゲーション コンポーネントは、Android ナビゲーション コンポーネントの上に構築されたライブラリです。 これにより、開発者はさまざまな画面モード用にフラグメント ナビゲーションを実装したり、既存のアプリケーションを折りたたみ型ナビゲーション パターンに対応させたりできます。

折りたたみ型ナビゲーション コンポーネントは、次の 3 つの主要部分で構成されています。

  • ナビゲーション グラフ - 1 つの一元化された場所にあるすべてのナビゲーション関連情報を含む XML リソース。 これは、Google によって提供されるナビゲーション コンポーネントのものと同じです。
  • FoldableNavHost - ナビゲーション グラフからのデスティネーションを表示する空のコンテナーです。 折りたたみ型ナビゲーションの実装は FoldableNavHostFragment です。
  • FoldableNavController - FoldableNavHost 内のアプリ ナビゲーションを管理するオブジェクト。

概要

デュアルスクリーンおよび折りたたみ型デバイス上のアプリケーションは、1 つの画面に表示することも、折りたたみ機能全体にわたって表示することもできます。 アプリケーションが最初に起動されたとき、次のようになります。

  • シングルスクリーンでは、1 つのフラグメント (A) のみが表示されます。
  • アプリケーションが折りたたみ機能全体にレンダリングされる場合、最初のフラグメント (A) は折りたたみの最初の側に表示され、もう一方の折りたたみは空白になります。

最初の状態から別のフラグメント (B) に移動すると、新しいフラグメントが最後の画面に開きます。

ユーザーが 3 番目のフラグメント (C) に移動した場合、それは最後の画面に表示され、前のフラグメント (B) は開始画面に移動されます。

  • アプリがまたがっている状態から 1 つの画面に移動されると、最後の画面のすべてのフラグメントが開始画面に移動され、(C) が上に表示されます。
  • アプリが 1 つの画面から折りたたみまたはヒンジにまたがるように移動され、ナビゲーション スタックに 2 つ以上のフラグメントがある場合、最後のフラグメントは最後の画面に移動します。

Six different dual-screen examples demonstrating how fragments A, B, and C would appear after different navigation steps

アクションの表示領域のデスティネーションを変更する

ナビゲーション グラフで launchScreen 属性を使用して、新しいフラグメントを表示する場所を指定できます。 launchScreen に指定できる値は次のとおりです。

  • start - フラグメントは、最初の画面に開きます
  • end - フラグメントは、2 番目の画面に開きます
  • both - フラグメントは表示領域全体を覆います

次のナビゲーション XML の例は、この属性の使用方法を示しています。

<navigation 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:id="@+id/home"
    app:startDestination="@+id/titleScreen">

    <fragment
        android:id="@+id/titleScreen"
        android:name="com.microsoft.device.dualscreen.navigation.sample.homescreen.TitleFragment"
        android:label="@string/title_home"
        tools:layout="@layout/fragment_title">
        <action
            android:id="@+id/action_title_to_about"
            app:launchScreen="end"
            app:destination="@id/aboutScreen"
            app:enterAnim="@anim/slide_in_right"
            app:exitAnim="@anim/slide_out_left"
            app:popEnterAnim="@anim/slide_in_right"
            app:popExitAnim="@anim/slide_out_left" />
    </fragment>
</navigation>

重要

この属性は、XML ファイルを直接編集することによってのみ変更できます。 Android Studio エディターを使用して変更することはできません。

サンプル

このナビゲーション サンプル アプリをダウンロードして、これらの動作すべてを表示できます。

ライブラリをプロジェクトにインポートする方法

  1. モジュールレベルの build.gradle ファイルに依存関係を追加します。

    dependencies {
       def nav_version = "1.0.0-alpha3"
       implementation "com.microsoft.device.dualscreen:navigation-fragment-ktx:$nav_version"
       implementation "com.microsoft.device.dualscreen:navigation-ui-ktx:$nav_version"
    }
    

  1. Java を使用してプロジェクトを作成する場合は、モジュールレベルの build.gradle ファイルに kotlin-stdlib 依存関係を追加する必要があります。 (これは、ライブラリの一部が Kotlin を使用して作成されたためです。)

    dependencies {
       implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
    }
    

これらのコンポーネントは、Google が提供するナビゲーション コンポーネント上に構築されているため、折りたたみ型ナビゲーション ライブラリには、それに対する依存関係が含まれています。

ナビゲーション グラフを作成する

ナビゲーション グラフは、目的地とアクションを使用した、すべてのアプリのナビゲーション パスを含む xml リソース ファイルです。 ナビゲーション グラフは、Android Studio Navigation Editor 経由で、または XML エディターを使用して手動で作成できます。 詳細については、「ナビゲーション グラフを作成する」を参照してください。

NavHost をアクティビティに追加する

折りたたみ型ナビゲーション コンポーネントは、1 つのメイン アクティビティと複数のフラグメント デスティネーションを持つアプリ向けに設計されています。 メイン アクティビティはナビゲーション グラフに関連付けられており、フラグメント デスティネーションを交換する役割を担う FoldableNavHostFragment が含まれます。 アプリに複数のアクティビティがある場合、各アクティビティには独自のナビゲーション グラフがあります。

以下はメイン アクティビティ XML レイアウト ファイルの例で、app:navGraph 属性の設定方法を示しています。

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/surface_duo_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.FoldableNavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>

FoldableNavHost は、プログラムを使用して設定することもできます。

val navHostFragment = FoldableNavHostFragment.create(navGraphId)
fragmentManager.beginTransaction()
    .add(containerId, navHostFragment, fragmentTag)
    .commitNow()

FoldableNavHost を追加する方法の詳細については、「NavHost をアクティビティに追加する」を参照してください。

このコード スニペットを使用すると、折りたたみ型ナビゲーション規則に従ってフラグメントをナビゲートできます。

class SomeFragment : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        view.findViewById<Button>(R.id.btn_next).setOnClickListener {
            findFoldableNavController().navigate(R.id.action_next)
        }
    }
}

FoldableNavigationUI を使用して UI コンポーネントを更新する

FoldableNavigationUI は、Jetpack ナビゲーション コンポーネントの NavigationUI に似たコンポーネントであり、最上位のアプリ バー、ナビゲーション ドロワー、下部ナビゲーションによりナビゲーションを管理する静的メソッドが含まれています。 詳細については、

FoldableNavigationUI には、NavigationUI によって提供されるものに似た次のメソッドがあります。

// same method name, with foldable parameter
boolean onNavDestinationSelected(MenuItem item, FoldableNavController navController)
boolean navigateUp(FoldableNavController navController, Openable openableLayout)
boolean navigateUp(FoldableNavController navController, FoldableAppBarConfiguration configuration)
// method name changed to reflect foldable navigation
void setupActionBarWithFoldableNavController(AppCompatActivity activity, FoldableNavController navController)
void setupActionBarWithFoldableNavController(AppCompatActivity activity, FoldableNavController navController, Openable openableLayout)
void setupActionBarWithFoldableNavController(AppCompatActivity activity, FoldableNavController navController, FoldableAppBarConfiguration configuration)
void setupWithFoldableNavController(Toolbar toolbar, FoldableNavController navController)
void setupWithFoldableNavController(Toolbar toolbar, FoldableNavController navController, Openable openableLayout)
void setupWithFoldableNavController(Toolbar toolbar, FoldableNavController navController, FoldableAppBarConfiguration configuration)
void setupWithFoldableNavController(CollapsingToolbarLayout collapsingToolbarLayout, Toolbar toolbar, FoldableNavController navController)
void setupWithFoldableNavController(CollapsingToolbarLayout collapsingToolbarLayout, Toolbar toolbar, FoldableNavController navController, Openable openableLayout)
void setupWithFoldableNavController(CollapsingToolbarLayout collapsingToolbarLayout, Toolbar toolbar, FoldableNavController navController, FoldableAppBarConfiguration configuration)
void setupWithFoldableNavController(NavigationView navigationView, FoldableNavController navController)
void setupWithFoldableNavController(BottomNavigationView bottomNavigationView, FoldableNavController navController)

既存のアプリケーションを折りたたみ型ナビゲーションに移行する

Google によって提供されるナビゲーション コンポーネントを使用する既存のアプリケーションでは、次の手順に従って、折りたたみ機能を追加できます。

  1. 以下のように、フラグメント コンテナーで NavHostFragment の代わりに FoldableNavHostFragment を使用します。

    <androidx.fragment.app.FragmentContainerView
         android:id="@+id/nav_host_fragment"
         android:name="androidx.navigation.NavHostFragment"
    

    to

    <androidx.fragment.app.FragmentContainerView
         android:id="@+id/nav_host_fragment"
         android:name="androidx.navigation.FoldableNavHostFragment"
    
  2. FoldableNavController のインスタンスを取得するには findFoldableNavController を使用し、またそれを使用して、以下のようにして、ナビゲーション グラフ内を移動します。

    findNavController().navigate(R.id.action_next)
    

    to

    findFoldableNavController().navigate(R.id.action_next)
    
  3. 以下のようにして、NavigationUI の代わりに FoldableNavigationUI を使用します。

    val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
    val navController = navHostFragment.navController
    val appBarConfiguration = AppBarConfiguration(navController.graph)
    setupActionBarWithNavController(navController, appBarConfiguration)
    

    to

    val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as FoldableNavHostFragment
    val navController = navHostFragment.navController
    val appBarConfiguration = FoldableAppBarConfiguration(navController.graph)
    setupActionBarWithFoldableNavController(navController, appBarConfiguration)