DrawerLayoutを利用すると通常であれば、NavigationUIを利用してDrawerLayoutに定義した静的な項目に対して選択をすると、Fragmentが切り替わるという動作を実装します。

ですが、DrawerLayoutにListViewを埋め込むことで動的な項目を選択できるようになります。

最終的にどんなイメージになるかというと以下です。

動きは以下のようになります。

 

今回の記事では、AndroidStudioでナビゲーション・ドロワー・アクティビティで新規プロジェクトを作成し、DrawerLayoutにListViewが以下のような形で表示できるところまでを書きたいと思います。

この記事での完成イメージ↓

1.新規プロジェクトの作成でナビゲーション・ドロワー・アクティビティを選択

以下のように「ナビゲーション・ドロワー・アクティビティ」を選択してプロジェクトを新規作成します。

2.activity_main.xmlにListViewを埋め込む

以下のように、activity_main.xmlのNavigationViewにListViewを埋め込むように修正します。
・変更前

    <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" />

・変更後

    <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" >
        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <include layout="@layout/nav_header_main"
                android:id="@+id/nav_header" />
            <ListView
                android:layout_weight="7"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:id="@+id/task_list_view_inside_nav">
            </ListView>
            <Button
                android:id="@+id/settings_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:text="@string/action_settings"/>
        </LinearLayout>
    </com.google.android.material.navigation.NavigationView>

3.content_main.xmlのnavigationを削除する

NavigationUIを利用してコンテンツが切り替わるように設定されている部分を削除します。
・変更前

    <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" />

・変更後

    <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" />

4.MainActivity.javaをListViewから選択するように実装する

MainActivityのonCreateメソッドを以下のようにListViewからFragmentを選択するような実装に修正します。

    private static final String lists[] = { "TASK1", "TASK2", "TASK3"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        FloatingActionButton fab = findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle actionBarDrawerToggle =
                new ActionBarDrawerToggle(
                        this, drawer, toolbar, R.string.drawer_open, R.string.drawer_close);
        drawer.addDrawerListener(actionBarDrawerToggle);
        actionBarDrawerToggle.syncState();

        NavigationView navigationView = findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                return false;
            }
        });

        ListView listView = findViewById(R.id.task_list_view_inside_nav);
        ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, lists);
        listView.setAdapter(arrayAdapter);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                FragmentManager fragmentManager = getSupportFragmentManager();
                switch (i) {
                    case 0:
                        Fragment galleryFragment = new GalleryFragment();
                        fragmentManager.beginTransaction().replace(R.id.nav_host_fragment, galleryFragment).commit();
                        break;
                    case 1:
                        Fragment homeFragment = new HomeFragment();
                        fragmentManager.beginTransaction().replace(R.id.nav_host_fragment, homeFragment).commit();
                        break;
                    case 2:
                        Fragment slideshowFragment = new SlideshowFragment();
                        fragmentManager.beginTransaction().replace(R.id.nav_host_fragment, slideshowFragment).commit();
                        break;
                }
                drawer.closeDrawers();
            }
        });
    }

以上で、修正は終わりとなります。
ビルドして動作確認をするとこの記事での完成イメージとして紹介した画面が表示されるのが確認できると思います。
 

最後に、冒頭で紹介した最終的なイメージについては、以下のアプリとしてGooglePlayに公開しているので動作の確認もできます。

シンプル操作でやることの管理ができる「記録が残るToDoリスト」

Todoを登録したり、完了した日時を自動で記録して履歴として表示することができる便利な機能が特徴です。

無料で公開しているので、ぜひダウンロードして日常使いのToDoリストとしても利用してみてください!