Android ActionBarとToolBarについてのメモ


この2つの違いが曖昧なので、調べたことをメモしておきます。

ActionBar

どこで定義されている?

まずActionBarについて。ActionBarはアプリのテーマとして自動で定義されているもの。定義は、AndroidManifest

<application
    <!-- 中略 -->
    android:theme="@style/AppTheme >

として記載されていて、変更したい場合は、style.xmlname="AppTheme"の要素に以下のように定義を追記したり、属性値を変更すればよい。

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- 中略 -->
    <item name="actionBarStyle">
    </item>
<style>

また、特別なことをしない限り自動でlayoutされ表示されます。

ActionBarの動作の記述

前述の通り、自動で生成されるViewですのでActivity内のコールバックメソッドで動作を記述するものがあります。以下は一例です。R.menu.~~~のリソースファイルについての説明は省略します。

class MainActivity : AppCompatActivity() {

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

        //タイトル名の変更
        supportActionBar?.title = "ActionBar"
        //タイトルラベルの左側のナビゲーションアイテムの設置
        supportActionBar?.setDisplayHomeAsUpEnabled(true)
        //ナビゲーションアイテムを変更
        supportActionBar?.setHomeAsUpIndicator(android.R.drawable.sym_def_app_icon)

        //タイトルラベル右側のメニューアイテムの設置
        override fun onCreateOptionsMenu(menu: Menu?): Boolean {
            getMenuInflater().inflate(R.menu.menu_item, menu);
        }

        //設置したアイテムのリスナーコールバック
        override fun onOptionsItemSelected(item: MenuItem?): Boolean {
    }    

onOptionsItemSelected()はすべてのアイテムからのコールバックとなるので、渡された引数MenuItem?からどのアイテムが選択されたかを調べて処理する必要があります。

ActionBarを表示しない

ActionBarを表示しないようにするには

アプリ全体

アプリ全体で非表示にするにはstyle.xmlAppTheme

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="windowNoTitle">true</item>
    <!-- 中略 -->
</style>

とします。

Activity個別

個別のActivityで制御する場合は、2種類の方法があります。

AndroidManifestで制御する

AndroidManifestで制御するには以下のようにandroid:themeを記述してActionBarを無効にします。

<activity
    android:name=".MainActivity"
    android:theme="@style/AppTheme.NoActionBar">
Actiityコードで制御する

Activityの上のコード制御するにはhide()メソッドを使用します。

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        supportActionBar?.hide()
    }    

但し、supportActionBar?.hide()をしたあとでsetSupportActionBar(toolbar)とするとクラッシュするので、toolbarを使用する時には注意。

ToolBar

ToolBarは各layoutに記述するViewとなります。ほぼActionBarと同等な機能を有しますが、CoordinatorLayoutと組み合わせて動的にlayout制御することができたり、カスタマイズしやすいコンポーネント(らしい)です。

定義

定義はlayoutにて以下のように記述します。

<android.support.v7.widget.Toolbar
           android:id="@+id/toolbar"
           android:layout_width="match_parent"
           android:layout_height="?attr/actionBarSize"
           android:background="?attr/colorPrimary"
           android:theme="@style/ThemeOverlay.AppCompat.ActionBar" />

ToolBar定義時のActionBar

また記述後、以下のようにActionBarとToolBarが重複して表示されるケースがあります。

f:id:letitride:20190610140611p:plain:h300

これは上記のActionBarの非表示化を行っていない為、ToolBarの上にActionBarが表示されてしまっている状態です。

また、画像のようにAppBarLayoutを使用した場合、ConstraintLayoutがToolBarの下に潜り込んでいる状態になる時があります。この場合、ConstraintLayoutにてapp:layout_behaviorを設定して問題を修正しました。

app:layout_behavior="@string/appbar_scrolling_view_behavior"

ToolBarの動作の記述

ToolBarはViewですので、他Viewと同様にメソッドにアクセスして利用します。

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_post_detail)
  
        //タイトルの変更
        toolbar.setTitle(post.title)
        //タイトルラベルの左側のナビゲーションアイテムの設置
        toolbar.setNavigationIcon(android.R.drawable.ic_delete)
        //ナビゲーションアイテムのリスナー
        toolbar.setNavigationOnClickListener {  }

        //タイトルラベルの右側のメニューアイテムの追加
        toolbar.inflateMenu(R.menu.menu_item)
        //メニューアイテムのリスナー
        toolbar.setOnMenuItemClickListener { menuItem ->
        }

ナビゲーションアイテムのリスナーは個別にありますが、メニューアイテムsetOnMenuItemClickListener()のリスナーは各アイテム共通ですので、引数menuItemからどのアイテムがClickされたかを判断して処理を記述します。

setSupportActionBar(toolbar)

setSupportActionBar()はToolBarをActionBarのメソッドを利用して操作できるAdapterのようです。既存で実装していたActionBarからToolBarに変更する時のサポートメソッドのように見受けられます?

このメソッドを実行したあとは、toolbar自体が持つメンバメソッドが機能しなくなるので注意します。