0Pricing
Android Academy · レッスン

ボトムナビゲーションとタブ

BottomNavigationViewをNavControllerに接続して複数セクションのナビゲーションを実装し、TabLayout、ViewPager2、TabLayoutMediatorでスワイプ可能なタブを作成します。

「ボトムナビゲーションとタブ」はCoddyKit上の無料Android Academyレッスンです。 これはレッスン5/5です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAndroid Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Android Academyコースには全5レッスンが含まれています。

ナビゲーションパターン

Androidアプリのトップレベルナビゲーションでよく使われる2つのパターンです:

  • Bottom Navigation — 3~5個の主要な遷移先に使用します。常に表示されます。重要度が同じセクション(例:ホーム、検索、プロフィール)に最適です。
  • Tabs — 1つの画面内にある関連コンテンツ(例:すべて/進行中/完了)に使用します。スワイプ操作に対応するため、ViewPager2と組み合わせることがよくあります。

BottomNavigationViewのレイアウト

ActivityのレイアウトにBottomNavigationViewとFragmentContainerViewを追加します:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/navHostFragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        app:navGraph="@navigation/nav_graph"
        app:defaultNavHost="true" />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottomNav"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:menu="@menu/bottom_nav_menu" />

</LinearLayout>

ボトムナビゲーションのメニュー項目

res/menu/bottom_nav_menu.xmlで項目を定義します。各項目のIDは、ナビゲーショングラフの遷移先IDと一致させる必要があります:

<!-- res/menu/bottom_nav_menu.xml -->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/homeFragment"
        android:icon="@drawable/ic_home"
        android:title="Home" />
    <item
        android:id="@+id/searchFragment"
        android:icon="@drawable/ic_search"
        android:title="Search" />
    <item
        android:id="@+id/profileFragment"
        android:icon="@drawable/ic_person"
        android:title="Profile" />
</menu>

NavControllerへの接続

onCreate()でBottomNavigationViewをNavControllerに接続します:

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val navHost = supportFragmentManager
            .findFragmentById(R.id.navHostFragment) as NavHostFragment
        val navController = navHost.navController

        binding.bottomNav.setupWithNavController(navController)

        // Hide bottom nav on detail screens:
        navController.addOnDestinationChangedListener { _, destination, _ ->
            binding.bottomNav.visibility = when (destination.id) {
                R.id.detailFragment -> View.GONE
                else -> View.VISIBLE
            }
        }
    }
}

ボトムナビゲーションのバッジ

ボトムナビゲーションの項目に通知バッジを表示します:

// Show a numbered badge:
val badge = binding.bottomNav.getOrCreateBadge(R.id.homeFragment)
badge.number = 5
badge.isVisible = true

// Show dot badge (no number):
val dotBadge = binding.bottomNav.getOrCreateBadge(R.id.searchFragment)
dotBadge.isVisible = true

// Remove badge:
binding.bottomNav.removeBadge(R.id.homeFragment)

TabLayout

TabLayoutは横方向のタブを表示します。通常は、スワイプ可能なコンテンツを表示するためにViewPager2と組み合わせて使用します:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tabLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

</LinearLayout>

ViewPager2 + FragmentStateAdapter

各タブの位置に対応するフラグメントを提供するアダプターを作成します:

class TasksPagerAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {

    override fun getItemCount() = 3

    override fun createFragment(position: Int): Fragment = when (position) {
        0 -> AllTasksFragment()
        1 -> ActiveTasksFragment()
        2 -> CompletedTasksFragment()
        else -> throw IllegalStateException("Unknown tab $position")
    }
}

TabLayoutMediator

TabLayoutMediatorでViewPager2とTabLayoutを接続します:

// In Fragment.onViewCreated():
val adapter = TasksPagerAdapter(this)
binding.viewPager.adapter = adapter

TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
    tab.text = when (position) {
        0 -> "All"
        1 -> "Active"
        2 -> "Done"
        else -> ""
    }
}.attach()

// Disable swipe if needed:
binding.viewPager.isUserInputEnabled = false

アイコン付きタブ

TabLayoutのタブにアイコンを追加します:

TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
    when (position) {
        0 -> {
            tab.text = "Home"
            tab.setIcon(R.drawable.ic_home)
        }
        1 -> {
            tab.text = "Search"
            tab.setIcon(R.drawable.ic_search)
        }
        2 -> {
            tab.text = "Profile"
            tab.setIcon(R.drawable.ic_person)
        }
    }
}.attach()

オフスクリーンページの上限

デフォルトでは、ViewPager2は隣接するページだけをメモリに保持します。切り替えた後もタブを保持したい場合は、offscreenPageLimitを増やします:

// Keep 2 pages on each side alive:
binding.viewPager.offscreenPageLimit = 2

// Note: FragmentStateAdapter saves and restores state for off-screen
// fragments even when offscreenPageLimit is 1 (default).
// Only increase this when you need views (not just state) to survive.

ボトムナビゲーションとタブの選び方

適切なパターンを選ぶための簡単な指針です:

  • Bottom Navigationを使用する:目的の異なるトップレベルの遷移先が3~5個ある場合(ホーム、検索、通知、プロフィール)
  • Tabsを使用する:同じ種類のコンテンツを絞り込んだり分類したりする場合(すべて/進行中/アーカイブ済みのタスク)
  • 両方を組み合わせる:トップレベルのセクションにはBottom Navを使用し、セクション内の絞り込みにはTabsを使用します

確認問題

TabLayoutをViewPager2に接続し、タブのラベルを設定するクラスはどれですか?

まとめ:ボトムナビゲーションとタブ

複数セクションのナビゲーションを正しく実装する方法:

  • BottomNavigationView — 重要度が同じ3~5個の遷移先。メニューIDはナビゲーショングラフの遷移先IDと一致させます
  • setupWithNavController() — タブの自動切り替えとバックスタック
  • getOrCreateBadge()によるバッジ
  • TabLayout + ViewPager2 — 同じコンテンツをスワイプして切り替えられる絞り込み表示
  • TabLayoutMediator — 2つを接続し、ラベルを設定します

次は、コードの信頼性を保つためのJUnitによるユニットテストです。

よくある質問

「ボトムナビゲーションとタブ」レッスンは無料ですか?

はい。「ボトムナビゲーションとタブ」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Android Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Android Academyコースには全5レッスンが含まれています。

「ボトムナビゲーションとタブ」で何を学びますか?

BottomNavigationViewをNavControllerに接続して複数セクションのナビゲーションを実装し、TabLayout、ViewPager2、TabLayoutMediatorでスワイプ可能なタブを作成します。 ブラウザで直接実行するハンズオンコードでAndroid Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Android Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのAndroid Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン5/5です。

「ボトムナビゲーションとタブ」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このAndroid Academyレッスンでコードを書いて実行できますか?

はい。すべてのAndroid Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. Material Designの基礎
  2. テーマとスタイル
  3. カスタムView
  4. アニメーションとトランジション
  5. ボトムナビゲーションとタブ
← Android Academyに戻る