Google は、黒人コミュニティに対する人種平等の促進に取り組んでいます。取り組みを見る

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

Navigation Architecture コンポーネントには、NavigationUI クラスがあります。このクラスには、トップ アプリバーやナビゲーション ドロワー、ボトム ナビゲーションを使用してナビゲーションを管理する静的メソッドが含まれています。

ナビゲーション イベントをリッスンする

デスティネーション間のナビゲーションは、主に NavController とのインタラクションによって実行されます。NavController は、NavHost のコンテンツを新しいデスティネーションに置き換える役割を担います。多くの場合、UI 要素(トップ アプリバーや、BottomNavigationBar のような永続的ナビゲーション コントロールなど)は、NavHost の外側に存在しており、デスティネーション間を移動する際に更新する必要があります。

NavController は、 の現在のデスティネーションまたはその引数が変更されたときに呼び出される OnDestinationChangedListener インターフェースを提供します。新しいリスナーは、addOnDestinationChangedListener() メソッドを通じて登録できます。addOnDestinationChangedListener() を呼び出したときに、現在のデスティネーションが存在した場合、すぐにリスナーに送信されます。

NavigationUI は、OnDestinationChangedListener を使用して、このような一般的な UI コンポーネントにナビゲーション認識機能を追加します。また、OnDestinationChangedListener を単独で使用して、カスタム UI やカスタム ビジネス ロジックにナビゲーション イベント認識機能を追加することもできます。

たとえば、アプリの一部の領域では表示し、他の領域では非表示にする一般的 UI 要素があるとします。独自の OnDestinationChangedListener を使用することで、ターゲット デスティネーションに基づいてこの UI 要素の表示 / 非表示を選択的に指定することができます。次の例をご覧ください。

Kotlin

    navController.addOnDestinationChangedListener { _, destination, _ ->
       if(destination.id == R.id.full_screen_destination) {
           toolbar.visibility = View.GONE
           bottomNavigationView.visibility = View.GONE
       } else {
           toolbar.visibility = View.VISIBLE
           bottomNavigationView.visibility = View.VISIBLE
       }
    }
    

Java

    navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
       @Override
       public void onDestinationChanged(@NonNull NavController controller,
               @NonNull NavDestination destination, @Nullable Bundle arguments) {
           if(destination.getId() == R.id.full_screen_destination) {
               toolbar.setVisibility(View.GONE);
               bottomNavigationView.setVisibility(View.GONE);
           } else {
               toolbar.setVisibility(View.VISIBLE);
               bottomNavigationView.setVisibility(View.VISIBLE);
           }
       }
    });
    

トップ アプリバー

トップ アプリバーは、アプリの上部に沿って同じ場所に配置され、現在の画面に基づく情報やアクションを表示します。

NavigationUI には、ユーザーがアプリ内を移動したときにトップ アプリバー内のコンテンツを自動的に更新するメソッドが含まれています。たとえば、 は、ナビゲーション グラフ内のデスティネーション ラベルを使用して、トップ アプリバーのタイトルを最新の状態に保ちます。

以下で説明するトップ アプリバー メソッドを使用して NavigationUI を使用した場合、デスティネーションにアタッチするラベルは、ラベル内で {argName} 形式を使用することで、デスティネーションに提供される引数に基づいて自動的に入力されます。

NavigationUI は、以下のタイプのトップ アプリバーをサポートしています。

AppBarConfiguration

NavigationUI は、AppBarConfiguration オブジェクトを使用して、アプリの表示領域の左上隅にあるナビゲーション ボタンの動作を管理します。デフォルトでは、ユーザーがナビゲーション グラフのトップレベル デスティネーションにいる場合、ナビゲーション ボタンは非表示になり、他のデスティネーションにいる場合は、[上へ] ボタンとして表示されます。

ナビゲーション グラフの開始デスティネーションを唯一のトップレベル デスティネーションとして使用するには、AppBarConfiguration オブジェクトを作成して、対象のナビゲーション グラフを渡します。以下をご覧ください。

Kotlin

    val appBarConfiguration = AppBarConfiguration(navController.graph)
    

Java

    AppBarConfiguration appBarConfiguration =
            new AppBarConfiguration.Builder(navController.getGraph()).build();
    

トップレベル デスティネーションとなるデスティネーションをカスタマイズする場合は、代わりに、デスティネーション ID のセットをコンストラクタに渡します。以下をご覧ください。

Kotlin

    val appBarConfiguration = AppBarConfiguration(setOf(R.id.main, R.id.android))
    

Java

    AppBarConfiguration appBarConfiguration =
            new AppBarConfiguration.Builder(R.id.main, R.id.android).build();
    

ツールバーを作成する

NavigationUI を使用してツールバーを作成するには、まず、メイン アクティビティ内でバーを定義します。以下をご覧ください。

    <LinearLayout>
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar" />
        <fragment
            android:id="@+id/nav_host_fragment"
            ... />
        ...
    </LinearLayout>
    

次に、メイン アクティビティの onCreate() メソッドから setupWithNavController() を呼び出します。以下をご覧ください。

Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {
        setContentView(R.layout.activity_main)

        ...

        val navController = findNavController(R.id.nav_host_fragment)
        val appBarConfiguration = AppBarConfiguration(navController.graph)
        findViewById<Toolbar>(R.id.toolbar)
            .setupWithNavController(navController, appBarConfiguration)
    }
    

Java

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.activity_main);

        ...

        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
        AppBarConfiguration appBarConfiguration =
                new AppBarConfiguration.Builder(navController.getGraph()).build();
        Toolbar toolbar = findViewById(R.id.toolbar);
        NavigationUI.setupWithNavController(toolbar, navController);
    }
    

CollapsingToolbarLayout を組み込む

ツールバーに CollapsingToolbarLayout を組み込むには、まず、メイン アクティビティ内でツールバーと周囲のレイアウトを定義します。以下をご覧ください。

    <LinearLayout>
        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="@dimen/tall_toolbar_height">

            <android.support.design.widget.CollapsingToolbarLayout
                android:id="@+id/collapsing_toolbar_layout"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:contentScrim="?attr/colorPrimary"
                app:expandedTitleGravity="top"
                app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

                <android.support.v7.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize"
                    app:layout_collapseMode="pin"/>
            </android.support.design.widget.CollapsingToolbarLayout>
        </android.support.design.widget.AppBarLayout>

        <fragment
            android:id="@+id/nav_host_fragment"
            ... />
        ...
    </LinearLayout>
    

次に、メイン アクティビティの onCreate メソッドから setupWithNavController() を呼び出します。以下をご覧ください。

Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {
        setContentView(R.layout.activity_main)

        ...

        val layout = findViewById<CollapsingToolbarLayout>(R.id.collapsing_toolbar_layout)
        val toolbar = findViewById<Toolbar>(R.id.toolbar)
        val navController = findNavController(R.id.nav_host_fragment)
        val appBarConfiguration = AppBarConfiguration(navController.graph)
        layout.setupWithNavController(toolbar, navController, appBarConfiguration)
    }
    

Java

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.activity_main);

        ...

        CollapsingToolbarLayout layout = findViewById(R.id.collapsing_toolbar_layout);
        Toolbar toolbar = findViewById(R.id.toolbar);
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
        AppBarConfiguration appBarConfiguration =
                new AppBarConfiguration.Builder(navController.getGraph()).build();
        NavigationUI.setupWithNavController(layout, toolbar, navController, appBarConfiguration);
    }
    

アクションバー

デフォルト アクションバーにナビゲーション サポートを追加するには、メイン アクティビティの onCreate() メソッドから setupActionBarWithNavController() を呼び出します。以下をご覧ください。AppBarConfiguration は、onSupportNavigateUp() をオーバーライドする際にも使用するため、onCreate() の外部で宣言する必要があります。

Kotlin

    private lateinit var appBarConfiguration: AppBarConfiguration

    ...

    override fun onCreate(savedInstanceState: Bundle?) {
        ...

        val navController = findNavController(R.id.nav_host_fragment)
        appBarConfiguration = AppBarConfiguration(navController.graph)
        setupActionBarWithNavController(navController, appBarConfiguration)
    }
    

Java

    AppBarConfiguration appBarConfiguration;

    ...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...

        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
        appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();
        NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
    }
    

次に、[上へ] ナビゲーションを処理する onSupportNavigateUp() をオーバーライドします。

Kotlin

    override fun onSupportNavigateUp(): Boolean {
        val navController = findNavController(R.id.nav_host_fragment)
        return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
    }
    

Java

    @Override
    public boolean onSupportNavigateUp() {
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
        return NavigationUI.navigateUp(navController, appBarConfiguration)
                || super.onSupportNavigateUp();
    }
    

デスティネーションとメニュー項目を結び付ける

NavigationUI は、デスティネーションをメニュー方式の UI コンポーネントに結び付けるヘルパーも提供します。NavigationUI には onNavDestinationSelected() ヘルパー メソッドが含まれており、このヘルパー メソッドは、MenuItem と、関連付けられたデスティネーションをホストする NavController を受け取ります。MenuItemid がデスティネーションの id と一致すると、NavController は、そのデスティネーションへのナビゲーションを実行します。

たとえば、以下の XML スニペットの場合、メニュー項目とデスティネーションを定義する際、共通の id である details_page_fragment を使用しています。

    <?xml version="1.0" encoding="utf-8"?>
    <navigation xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:android="http://schemas.android.com/apk/res/android"
        ... >

        ...

        <fragment android:id="@+id/details_page_fragment"
             android:label="@string/details"
             android:name="com.example.android.myapp.DetailsFragment" />
    </navigation>
    
    <menu xmlns:android="http://schemas.android.com/apk/res/android">

        ...

        <item
            android:id="@id/details_page_fragment"
            android:icon="@drawable/ic_details"
            android:title="@string/details" />
    </menu>
    

たとえば、アクティビティの onCreateOptionsMenu() を通じてメニューを追加した場合、アクティビティの onOptionsItemSelected() をオーバーライドして onNavDestinationSelected() を呼び出すことで、メニュー項目をデスティネーションに関連付けることができます。以下をご覧ください。

Kotlin

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        val navController = findNavController(R.id.nav_host_fragment)
        return item.onNavDestinationSelected(navController) || super.onOptionsItemSelected(item)
    }
    

Java

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
        return NavigationUI.onNavDestinationSelected(item, navController)
                || super.onOptionsItemSelected(item);
    }
    

以上の設定により、ユーザーが details_page_fragment メニュー項目をタップすると、同じ id を持つデスティネーションに自動的に移動するようになります。

ナビゲーション ドロワーを追加する

ナビゲーション ドロワーは、アプリのメイン ナビゲーション メニューを表示する UI パネルです。ドロワーは、ユーザーがアプリバー内のドロワー アイコン()をタップしたときや、画面の左端からスワイプしたときに表示されます。

ドロワー アイコンは、DrawerLayout を使用しているすべてのトップレベル デスティネーション上で表示されます。トップレベル デスティネーションは、アプリのルートレベル デスティネーションです。トップレベル デスティネーションの場合、アプリバーに [上へ] ボタンは表示されません。

ナビゲーション ドロワーを追加するには、まず、DrawerLayout をルートビューとして宣言します。DrawerLayout 内に、メイン UI コンテンツのレイアウトと、ナビゲーション ドロワーのコンテンツを格納する別のビューを追加します。

たとえば、下記のレイアウトの場合、2 つの子ビューを持つ DrawerLayout を使用しています。一方の子ビューは、メイン コンテンツを格納する NavHostFragment で、もう一方の子ビューは、ナビゲーション ドロワーのコンテンツ用の NavigationView です。

<?xml version="1.0" encoding="utf-8"?>
    <!-- Use DrawerLayout as root container for activity -->
    <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true">

        <!-- Layout to contain contents of main body of screen (drawer will slide over this) -->
        <fragment
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:id="@+id/nav_host_fragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:defaultNavHost="true"
            app:navGraph="@navigation/nav_graph" />

        <!-- Container for contents of drawer - use NavigationView to make configuration easier -->
        <android.support.design.widget.NavigationView
            android:id="@+id/nav_view"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:fitsSystemWindows="true" />

    </android.support.v4.widget.DrawerLayout>
    

次に、AppBarConfiguration に渡すことによって、DrawerLayout をナビゲーション グラフに接続します。以下をご覧ください。

Kotlin

    val appBarConfiguration = AppBarConfiguration(navController.graph, drawerLayout)
    

Java

    AppBarConfiguration appBarConfiguration =
            new AppBarConfiguration.Builder(navController.getGraph())
                .setDrawerLayout(drawerLayout)
                .build();
    

次に、メイン アクティビティ クラス内で、メイン アクティビティの onCreate() メソッドから setupWithNavController() を呼び出します。以下をご覧ください。

Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {
        setContentView(R.layout.activity_main)

        ...

        val navController = findNavController(R.id.nav_host_fragment)
        findViewById<NavigationView>(R.id.nav_view)
            .setupWithNavController(navController)
    }
    

Java

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.activity_main);

        ...

        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
        NavigationView navView = findViewById(R.id.nav_view);
        NavigationUI.setupWithNavController(navView, navController);
    }
    

ボトム ナビゲーション

NavigationUI は、ボトム ナビゲーションも処理できます。ユーザーがメニュー項目を選択すると、NavController は、onNavDestinationSelected() を呼び出して、ボトム ナビゲーション バー内で選択されているアイテムを自動的に更新します。

アプリ内にボトム ナビゲーション バーを作成するには、まず、メイン アクティビティ内でバーを定義します。以下をご覧ください。

    <LinearLayout>
        ...
        <fragment
            android:id="@+id/nav_host_fragment"
            ... />
        <android.support.design.widget.BottomNavigationView
            android:id="@+id/bottom_nav"
            app:menu="@menu/menu_bottom_nav" />
    </LinearLayout>
    

次に、メイン アクティビティ クラス内で、メイン アクティビティの onCreate() メソッドから setupWithNavController() を呼び出します。以下をご覧ください。

Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {
        setContentView(R.layout.activity_main)

        ...

        val navController = findNavController(R.id.nav_host_fragment)
        findViewById<BottomNavigationView>(R.id.bottom_nav)
            .setupWithNavController(navController)
    }
    

Java

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.activity_main);

        ...

        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
        BottomNavigationView bottomNav = findViewById(R.id.bottom_nav);
        NavigationUI.setupWithNavController(bottomNav, navController);
    }
    

ボトム ナビゲーションを含む包括的な例については、GitHub の Android Architecture Components 高機能ナビゲーション サンプルをご覧ください。

参考リンク

ナビゲーションについて詳しくは、以下の参考情報をご確認ください。

サンプル

コードラボ

ブログ記事

動画