Android Activity、Fragment應用欄(AppBar)使用

簡要

AppBar應用欄,提供固定的位置,用於顯示當前屏幕與操作

Activity擁有應用欄:Fragment變更/擴充菜單,用途每個介面皆需要應用欄,但Fragment的應用欄選項皆不同時,可以有效的讓各個介面有更好的規劃

Fragment擁有應用欄:大部分皆不需要應用欄,只有特定的Fragment需要時,會採用此方法

Menu的一些設置參考Android Menu showAsAction屬性

由ActionBar更換Toolbar,以及Toolbar一些設置參考Android ActionBar與Toolbar

以下分成幾個區塊介紹

  1. Activity擁有應用欄
  2. Fragment擁有應用欄
  3. 動態修改Menu是否顯示
  4. Menu點擊事件處理

1. Activity擁有應用欄

了解Menu基本的設定後,建立好的Menu該如何設定呢?


Activity擁有應用欄,意味著Activity與Fragment皆有Menu且是用共的,因為Activity擁有

用途:每個介面皆需要應用欄,但Fragment的應用欄選項皆不同時

首先先幫Activity與Fragment建立一個不一樣的Menu,方便觀察效果

Activity Menu如下

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item android:id="@+id/searchMenu"
        app:actionViewClass="android.widget.SearchView"
        android:icon="@drawable/ic_baseline_search_24"
        android:title="search"
        app:showAsAction="ifRoom|collapseActionView" />
    <item android:id="@+id/testMenu"
        android:icon="@drawable/ic_baseline_fast_forward_24"
        android:title="test2"
        app:showAsAction="ifRoom"/>
</menu>

Fragment Menu如下

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/backButton"
android:icon="@drawable/ic_baseline_chevron_left_24"
app:showAsAction="ifRoom"
android:title="test1"/>
<item android:id="@+id/testMenu2"
android:icon="@drawable/ic_baseline_favorite_24"
app:showAsAction="ifRoom"
android:title="test2"/>
</menu>

建立完後

Activity中新增下列程式碼

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.activity_menu, menu)
return true
}

Fragment中新增以下程式碼

override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.fragment_menu, menu)
//切換到這個Fragment時,不需要使用searchMenu
menu.findItem(R.id.searchMenu).isVisible = false
}

在Fragment onCreated中新增,向Activity註冊使用

setHasOptionsMenu(true)

這樣在這個Fragment時,就有專屬的Menu選項,其他的頁面,皆顯示Activity的Menu

有設定專屬Menu的Fragment介面
沒設定Menu的Fragment,依照Activity Menu顯示

2. Fragment擁有應用欄

用途:大部分皆不需要應用欄,只有特定的Fragment需要時,會採用此方法

首先先把Activity的ActionBar隱藏

supportActionBar?.hide()
binding.mToolbar.visibility = View.GONE

隱藏後在Fragment的Layout新建

<androidx.appcompat.widget.Toolbar
android:id="@+id/mToolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
app:layout_constraintVertical_bias="0"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<TextView
android:id="@+id/titleTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="title"
android:textSize="20dp"
android:textColor="@color/white"
android:layout_gravity="center"/>
</androidx.appcompat.widget.Toolbar>

接著在onViewCreated裡面新增下列程式碼,這樣就新增好Menu了

binding.mToolbar.inflateMenu(R.menu.fragment_menu)

如果要更換Menu方式也很簡單

這裡設定一個Button按下時變更Menu

binding.replaceMenuBtn.setOnClickListener {
    clearToolbarMenu()
    if(!isChangeMenu) {
        binding.mToolbar.inflateMenu(R.menu.activity_menu)
    } else {
        binding.mToolbar.inflateMenu(R.menu.fragment_menu)
    }
    isChangeMenu = !isChangeMenu
}

private fun clearToolbarMenu() {
    binding.mToolbar.menu.clear()
}

3. 動態修改Menu是否顯示

這裡分為兩部分

a. Activity擁有應用欄

在Fragment中,新增以下程式碼

private var isEditMenu = false
override fun onPrepareOptionsMenu(menu: Menu) {
    super.onPrepareOptionsMenu(menu)
    val item = menu.findItem(R.id.backButton)
    item.isVisible = isEditMenu
}

並設定一個Button,按下時,顯示/隱藏Menu

binding.replaceMenuBtn.setOnClickListener {
    isEditMenu = !isEditMenu
    requireActivity().invalidateOptionsMenu()
}

b. Fragment擁有應用欄

使用相對比較簡單一點,方式如下

在Fragment中,新增以下程式碼

private fun updateToolbar() {
    isEditMenu = !isEditMenu

    val saveItem = binding.mToolbar.menu.findItem(R.id.testMenu2)
    saveItem.isVisible = isEditMenu
}

設定一個Button,按下時,顯示/隱藏Menu

binding.backBtn.setOnClickListener {
updateToolbar()
}

4. Menu點擊事件處理

這裡分為兩部分

a. Activity擁有應用欄

在Fragment裡面新增下列程式碼

override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when(item.itemId) {
R.id.testMenu2 -> {
true
}
else -> {
super.onOptionsItemSelected(item)
}
}
}

如果是這個按鈕則攔截(設為true),否則不攔截給Activity處理(設為super.onOptionsItemSelected(item))

在Activity中新增下列程式碼

override fun onOptionsItemSelected(item: MenuItem): Boolean {
    return when(item.itemId) {
        R.id.searchMenu -> {
            true
        }
        R.id.testMenu -> {
            true
        }
        R.id.testMenu2 -> {
            true
        }
        else -> super.onOptionsItemSelected(item)
    }
}

這樣設定完後,Fragment沒攔截的按鈕就可以在Activity中操作

b. Fragment擁有應用欄

監聽的方式與Activity擁有應用欄不太一樣,使用方式如下

binding.mToolbar.setOnMenuItemClickListener {
when(it.itemId) {
R.id.testMenu2 -> {
println("test")
true
}
else -> false
}
}

以上內容參考Android 官網


相關文章

Android Menu showAsAction屬性Android ActionBar與Toolbar
1. 簡要
2. Menu的showAsAction屬性介紹
簡要
1. 如何將預設ActionBar關閉,改用Toolbar呢?
2. Toolbar Title如何置中呢?
3. 為Toolbar設定Menu

訂閱Codeilin的旅程,若有最新消息會通知。

廣告

對「Android Activity、Fragment應用欄(AppBar)使用」的一則回應

Add yours

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s

WordPress.com.

向上 ↑

%d 位部落客按了讚: