3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

この記事誰得? 私しか得しないニッチな技術で記事投稿!

AndroidでToolbarを使って見る

Last updated at Posted at 2023-06-27

ActionbarからToolbarへ

前回、ActionBarをFragmentに対応させるでActionbarをActivity、と複数フラグメントに対応させましたが、googleは今はActionbarではなくて、Toolbarを推奨しています。

公式ページ:アプリバーの追加

公式では、ActionbarやToolbarのように画面の上部に表示されるばーを「アプリバー」と総称しています。

ActionbarとToolbarの大きな違いは

  • Actionbarはthemesの一部
  • ToolbarはLayoutの部品

が大きな違いです。

themes.xml

themes.xmlの親スタイルはActionbarの場合は
parent="Theme.MaterialComponents.DayNight.DarkActionBar"
でしたが、Toolbarの場合は
parent="Theme.MaterialComponents.DayNight.NoActionBar"
もしくは
parent="Theme.Material3.DayNight.NoActionBar"
となります。Material3では、DarkActionBarは既になくなっています。Material3ではActionbarはもう使うなってことなんでしょうかね?

themes.xml
<resources xmlns:tools="http://schemas.android.com/tools">
    <style name="Base.Theme.Toolbar" parent="Theme.Material3.DayNight.NoActionBar">
    ・・・
</resources>

nightテーマの方のthemes.xmlも同様に修正します。

メニュー定義ファイル

Toolbarのアイコン、メニューを定義するメニュー定義ファイルはActionbarもToolbarも同じなのでそのまま使います。

レイアウト、activity_main.xml

Toolbarはレイアウトの中のひとつの部品なのでactivity_main.xmlの上部に配置します。その下にFragmentContainerViewを配置します。Toolbar以外の残りはFragmentContainerViewが目いっぱい、画面全体を覆うようにします。この、FragmentContainerViewをクルクルとFragmentを入れ替えて画面遷移します。

公式ではToolbarの部品に
android.support.v7.widget.Toolbar
を使っていますが、これは古いようです。最新版は
androidx.appcompat.widget.Toolbar
を使います。

activity_main.xml
<?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"
    tools:context=".MainActivity">
    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:elevation="10dp"
        android:minHeight="?attr/actionBarSize"
        android:theme="?attr/actionBarTheme"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/fragmentContainerView"
        android:name="com.example.toolbar.Fragment1"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/toolbar"
        app:layout_constraintVertical_bias="1.0" />
</androidx.constraintlayout.widget.ConstraintLayout>

Toolbarの設定値でテーマの設定値を適用する場合は?attrを使います。

  • ?attr/actionBarSize バーの縦サイズ
  • ?attr/colorPrimary テーマのPrimaryの色
  • ?attr/actionBarTheme バーのテーマ

スクリーンショット 2023-06-27 101009.png

MainActivity、Fragmentの作り

MainActivityはActionbarの時と同じように、MainActivity側にToolbarの設定、menuのinflateを集約します。Fragment側は各Fragmentで異なる場合、Toolbarのアイコン、メニューの表示、非表示だけを制御します。

MainActivity.kt
class MainActivity : AppCompatActivity() {
   /** ViewBinding */
   private lateinit var binding: ActivityMainBinding

    /**
     * アクティビティの初期化
     * @param[savedInstanceState] Bundle
     */
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater).apply {
            setContentView(this.root)
        }
        val toolbar = binding.toolbar.apply {
            setLogo(R.mipmap.ic_launcher)
            title = "タイトル"
            setTitleTextColor(Color.WHITE)
            subtitle = "サブタイトル"
            setSubtitleTextColor(Color.GRAY)
        }
        setSupportActionBar(toolbar)
    }
    ・・・
}

レイアウト上に配置してある部品なので普通にviewBindingで取得してプロパティを設定します。サブタイトルは例として設定しいますが。マテリアルデザインでは非推奨となっています。

メニューのinflateとアクションの追加

公式ではアクションへの対応で、onOptionsItemSelected関数を実装していますが、この実装は古いようです。

前回、ActionBarをFragmentに対応させるでの例と同様に
androidx.core.view.MenuHost
androidx.core.view.MenuProvider
を使います。これはそっくり、そのままActionbarの時と同じ実装が使えます。

MainActivity.kt
    private fun setupMenuBar() {
        addMenuProvider(object : MenuProvider {
            override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
                menuInflater.inflate(R.menu.menu_sample, menu)
            }
            override fun onMenuItemSelected(item: MenuItem): Boolean {
                when (item.itemId) {
                    R.id.iconItem1 -> {
                        ・・・
                    }
                    ・・・
                    else -> {}
                }
                return true
            }
        })
    }

Fragment側も、そのままActionbarの時と同じ実装が使えます。

Fragment1.kt
    private fun setupMenuBar() {
        val menuHost: MenuHost = requireActivity()
        menuHost.addMenuProvider(object : MenuProvider {
            override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
                // Fragmentの場合はinflateしなくていい
            }
            override fun onPrepareMenu(menu: Menu) {
                // Fragment毎に、ActionBarのicon、menuの表示/非表示を制御する場合はここでやる
                menu.findItem(R.id.iconItem1).isVisible = false
                menu.findItem(R.id.iconItem2).isVisible = true
                ・・・
            }
            override fun onMenuItemSelected(item: MenuItem): Boolean {
                // アイコン、メニューが押された場合のハンドリングはMainActivityでやる
                return true
            }
        }, viewLifecycleOwner, Lifecycle.State.RESUMED)
    }

Fragment側で実装すべきなのはMenuProvider#onPrepareMenu関数だけです。ここは各Fragment毎に表示するアイコンメニューを変えるため、表示、非表示の制御をします。

ActionbarからToolbarへの書き換えは意外と簡単

以上のように、ActionbarとToolbarで違うのは

  • themes.xml(dayLight、night)の親スタイル
  • activitymain.xmlにToolbarを配置
  • MainActivity.ktでToolbarの初期化と設定

なので意外と簡単です。

最後に

ソースはgitHubにpushしました

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?