web-dev-qa-db-ja.com

Androidのナビゲーションドロワーでナビゲーションコンポーネントを設定する方法

ナビゲーションドロワーでナビゲーションコンポーネントを設定するにはどうすればよいですか?アプリでどのように使用しますか?

1つのアクティビティですべてを実行できますか?

動的なツールバーの可視性を持つ1つのアクティビティとフラグメントのみでツールバーの可視性を処理する方法また、引き出しを閉じてアクセスできないようにするために必要な破片があります。

この質問は自己回答型の質問であり、実際のQAよりもチュートリアルとして機能します。

3

ナビゲーションドロワーでナビゲーションコンポーネントを設定するにはどうすればよいですか?

アプリでどのように使用しますか?

ナビゲーションコンポーネントに関しては、ナビゲーションドロワーの設定が少し異なります。

注、ドロワーナビゲーションで新しいアプリを作成する場合、現在のチュートリアルは必要ありません。ただし、ここで奇妙に見える可能性があること、およびアプリの後の段階で引き出しを追加することにした場合について説明します

最初に、ナビゲーションアーキテクチャに対応できるように_activity_main.xml_とMainActivityを設定する必要があります。

_<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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/drawer_layout"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <include
        layout="@layout/app_bar_main"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent" />

    <com.google.Android.material.navigation.NavigationView
        Android:id="@+id/nav_view"
        Android:layout_width="wrap_content"
        Android:layout_height="match_parent"
        Android:layout_gravity="start"
        Android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer" />

</androidx.drawerlayout.widget.DrawerLayout>
_

ここで、_app_bar_main_は次のとおりです。

_<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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">

    <com.google.Android.material.appbar.AppBarLayout
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:theme="@style/AppTheme.AppBarOverlay">

        <androidx.appcompat.widget.Toolbar
            Android:id="@+id/toolbar"
            Android:layout_width="match_parent"
            Android:layout_height="?attr/actionBarSize"
            Android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </com.google.Android.material.appbar.AppBarLayout>

    <include layout="@layout/content_main" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>
_

そして、_content_main_はフラグメントが保持される場所です:

_<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:showIn="@layout/app_bar_main">

    <fragment
        Android:id="@+id/nav_Host_fragment"
        Android:name="androidx.navigation.fragment.NavHostFragment"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/mobile_navigation" />
</androidx.constraintlayout.widget.ConstraintLayout>
_

知っておくべきこと:_AndroidManifest.xml_でアクティビティにAppBarを設定してはいけません:

_Android:theme="@style/AppTheme.NoActionBar"
_

NavigationViewタグで_app:menu="@menu/activity_main_drawer"_に気づいた場合、フラグメント名は_mobile_navigation.xml_内と同じである必要があります。

_<group Android:checkableBehavior="single">
        <item
            Android:id="@+id/homeFragment"
            Android:icon="@drawable/ic_menu_camera"
            Android:title="@string/menu_home" />
        <item
            Android:id="@+id/galleryFragment"
            Android:icon="@drawable/ic_menu_gallery"
            Android:title="@string/menu_gallery" />
        <item
            Android:id="@+id/slideshowFragment"
            Android:icon="@drawable/ic_menu_slideshow"
            Android:title="@string/menu_slideshow" />
        <item
            Android:id="@+id/toolsFragment"
            Android:icon="@drawable/ic_menu_manage"
            Android:title="@string/menu_tools" />
    </group>

    <item Android:title="Communicate">
        <menu>
            <item
                Android:id="@+id/shareFragment"
                Android:icon="@drawable/ic_menu_share"
                Android:title="@string/menu_share" />
            <item
                Android:id="@+id/sendFragment"
                Android:icon="@drawable/ic_menu_send"
                Android:title="@string/menu_send" />
        </menu>
    </item>

</menu>
_

このように、以下で説明することにより、クリックを検出するためにonCreateOptionsMenuを呼び出す必要がなくなります。 Androidチームはすでに解決済みです。以下に従ってください。

これまでのところ、これは私たちが実際に行う通常の引き出しの設定とあまり変わりません。ただし、アプリのロジック部分で実行する必要があるいくつかの構成があります。では、_MainActivity.kt_を開いてみましょう。まず、これらが必要になります:

_  private var appBarConfiguration: AppBarConfiguration? = null
  private var drawerLayout: DrawerLayout? = null
  private var toolbar: Toolbar? = null
  private var navController: NavController? = null
_

その後、onCreateメソッドで:

_override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        toolbar = findViewById(R.id.toolbar)
        setSupportActionBar(toolbar) //set the toolbar

        drawerLayout = findViewById(R.id.drawer_layout)
        val navView: NavigationView = findViewById(R.id.nav_view)
        navController = findNavController(R.id.nav_Host_fragment)
        appBarConfiguration = AppBarConfiguration(
            setOf(
                R.id.homeFragment,
                R.id.galleryFragment,
                R.id.slideShowFragment,
                R.id.toolsFragment,
                R.id.shareFragment,
                R.id.sendFragment,
                R.id.loginFragment,
                R.id.phoneConfirmationFragment
            ), drawerLayout
        )

        setupActionBarWithNavController(navController!!, appBarConfiguration!!) //the most important part
        navView.setupWithNavController(navController!!) //the second most important part

      //other things unrelated
    }
_

ここで何が起こっているのか見てみましょう:

最初に、navControllerへの参照が必要になります。 AppBarConfigurationは、最上位の宛先として開かれるフラグメントを保持するクラスです。つまり、開かれたフラグメントは現在のフラグメントをフラグメントバックスタックから解放します。 AppBarConfigurationにもドロワーがあることを伝えることが重要です(コンストラクターのパラメーターとして渡されます)。

その下には、onSupportNavigateUp()というメソッドがあります。

_override fun onSupportNavigateUp(): Boolean {
        val navController = findNavController(R.id.nav_Host_fragment)
        return navController.navigateUp(appBarConfiguration!!) || super.onSupportNavigateUp()
    }
_

このメソッドは、[戻る]ボタンと関係があります。しかし、引き出しのナビゲーションがあれば、それはあまり必要ありません。これは、バックスタックに追加されたフラグメントが多数(または少なくとも2つ)ある場合に非常に便利です。

すべてを1つのアクティビティで実行できますか?

はい、間違いなく!しかし、条件付きナビゲーションに関しては、まだ少し作業が必要です。引き出しアプリの一部ではないフラグメントを表示したいときのように。しかし、それでもグーグルはそれで大きな進歩を遂げました。条件付きナビゲーション here を参照できます。

動的なツールバーの可視性を持つ1つのアクティビティとフラグメントのみでツールバーの可視性を処理する方法また、引き出しを閉じてアクセスできないようにするために必要な破片があります。

addOnDestinationChangedListenerからnavControllerを使用できます。

_navController.addOnDestinationChangedListener { _, destination, _ ->
            when (destination.id) {
                R.id.loginFragment, R.id.registerFragment, R.id.phoneConfirmationFragment -> {
                    toolbar?.visibility = View.GONE
                    drawerLayout?.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
                }
                else -> {
                    toolbar?.visibility = View.VISIBLE
                    drawerLayout?.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
                }
            }
        }
_

これで、アプリにドロワーとナビゲーションコンポーネントができました。

2