Toolbar使用總結
Toolbar 繼承的是ViewGroup,用來替代原來的ActionBar

一個Toolbar 從左到右包括了 一個navigation button、一個logo、一個title和subtitle、一個或多個自定義的View和一個 action menu 這5部分

基本屬性設定
- 在佈局檔案中設定
- app:navigationIcon 設定navigation button
- app:logo 設定logo 圖示
- app:title 設定標題
- app:titleTextColor 設定標題文字顏色
- app:subtitle 設定副標題
- app:subtitleTextColor 設定副標題文字顏色
- app:popupTheme Reference to a theme that should be used to inflate popups shown by widgets in the toolbar.
- app:titleTextAppearance 設定title text 相關屬性,如:字型,顏色,大小等等
- app:subtitleTextAppearance 設定subtitletext相關屬性,如:字型,顏色,大小等等
- app:logoDescription logo 描述
- android:background Toolbar 背景
- android:theme 主題
- 在Java中設定
mToolbar = findViewById(R.id.toolbar); mMenuView = findViewById(R.id.toolbar_action_menu); mToolbar.setTitle("John"); mToolbar.setNavigationIcon(R.drawable.ic_menu); mToolbar.setNavigationOnClickListener(this::OnBackClick); mToolbar.setSubtitle("Sub"); //設定溢位選單的圖示 //mToolbar.setOverflowIcon(ContextCompat.getDrawable(getApplicationContext(),R.drawable.menu)); mToolbar.inflateMenu(R.menu.toolbar_menu); mToolbar.setOnMenuItemClickListener(menuItem -> { //利用colorFilter動態更改圖示顏色 //menuItem.getIcon().setColorFilter(Color.parseColor("#223344"),PorterDuff.Mode.MULTIPLY); switch (menuItem.getItemId()){ case R.id.toolbar_call: Toast.makeText(MainActivity.this,"toolbar_call",Toast.LENGTH_SHORT).show(); break; case R.id.toolbar_delete: Toast.makeText(MainActivity.this,"toolbar_delete",Toast.LENGTH_SHORT).show(); break; case R.id.toolbar_mail: Toast.makeText(MainActivity.this,"toolbar_mail",Toast.LENGTH_SHORT).show(); break; } return true; }); 複製程式碼
亦可以通過 setSupportActionbar
,再呼叫 getSupportActionBar
,當成actionBar使用,若沒有則, setSupportActionbar
,則 onCreateOptionsMenu
不會回撥
Toolbar 的使用
- 更改Android “AppTheme”,指定為
Theme.AppCompat.Light.NoActionBar
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> <!--更改menu item間隔--> <item name="android:actionButtonStyle">@style/MyActionButtonStyle</item> </style> 複製程式碼
MyActionButtonStyle:
<!--menu item 之間的間隔--> <style name="MyActionButtonStyle" parent="Widget.AppCompat.ActionButton"> <item name="android:minWidth">72dip</item> </style> 複製程式碼
- 在佈局檔案中新增Toolbar
<android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="0dp" android:layout_height="?attr/actionBarSize" android:background="@color/colorPrimary" android:theme="@style/MyToolBarTheme" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent"> </android.support.v7.widget.Toolbar> 複製程式碼
MyToolbarTheme:
<style name="MyToolBarTheme" parent="ThemeOverlay.AppCompat.Dark.ActionBar"> <!--更改溢位選單文字顏色--> <item name="android:textColor">@color/colorAccent</item> <!--更改toolbar選單文字大小,包括溢位選單上的,和顯示上的--> <item name="android:textSize">25sp</item> <!--更改toolbar上的選單顯示文字顏色--> <item name="android:actionMenuTextColor">@color/colorPrimaryDark</item> <!-- 設定Menu視窗不覆蓋Toolbar檢視 --> <item name="overlapAnchor">false</item> <!--設定title與navigationIcon的間隔--> <item name="contentInsetStart">0dp</item> <item name="contentInsetLeft">0dp</item> <item name="contentInsetStartWithNavigation">0dp</item> </style> 複製程式碼
- 在java中獲取toolbar並設定屬性
Toolbar特殊需求使用
- 更改溢位選單文字顏色

指定MyToolbarTheme(如上),新增:
<item name="android:textColor">@color/colorAccent</item>
- 更改toolbar選單文字大小,包括溢位選單上的,和顯示上的
指定MyToolbarTheme(如上),新增: <item name="android:textSize">25sp</item>
- 更改toolbar上的選單顯示文字顏色

<item name="android:actionMenuTextColor">@color/colorPrimaryDark</item>
- 設定Menu視窗不覆蓋Toolbar檢視

<item name="overlapAnchor">false</item>
- 設定title與navigationIcon的間隔

指定MyToolbarTheme(如上),新增:
<item name="contentInsetStart">0dp</item> <item name="contentInsetLeft">0dp</item> <item name="contentInsetStartWithNavigation">0dp</item> 複製程式碼
- 設定menu item 之間的間隔

在“AppTheme”中,新增:
<item name="android:actionButtonStyle">@style/MyActionButtonStyle</item>
MyActionButtonStyle:
<style name="MyActionButtonStyle" parent="Widget.AppCompat.ActionButton"> <item name="android:minWidth">72dip</item> </style> 複製程式碼
- 標題居中

在Toolbar裡面放置一個TextView控制元件作為居中的標題來使用,再將Toolbar的Title隱藏起來即可實現Toolbar標題居中的效果

若有使用 setSupportActionBar()
,則呼叫 getSupportActionBar().setDisplayShowTitleEnabled(false);
隱藏標題;若沒設定,只要toolbar不設定title即可
ActionMenuView
選單預設在最右邊,使用ActionMenuView可更改選單顯示位置,並可以動態刪除新增選單

- 在toolbar中增加ActionMenuView

- 在java中動態載入選單和設定監聽
mMenuView = findViewById(R.id.toolbar_action_menu); //載入選單 getMenuInflater().inflate(R.menu.toolbar_menu,mMenuView.getMenu()); //設定選單監聽 mMenuView.setOnMenuItemClickListener(menuItem -> { switch (menuItem.getItemId()){ case R.id.toolbar_call: Toast.makeText(MainActivity.this,"toolbar_call",Toast.LENGTH_SHORT).show(); break; case R.id.toolbar_delete: Toast.makeText(MainActivity.this,"toolbar_delete",Toast.LENGTH_SHORT).show(); break; case R.id.toolbar_mail: Toast.makeText(MainActivity.this,"toolbar_mail",Toast.LENGTH_SHORT).show(); break; } //動態改變選單 mMenuView.getMenu().clear(); getMenuInflater().inflate(R.menu.nav_menu,mMenuView.getMenu()); return true; }); 複製程式碼
app:actionViewClass

<item android:id="@+id/toolbar_delete" android:title="delete" android:icon="@drawable/ic_delete" app:actionViewClass="android.widget.Button" app:showAsAction="always"/> 複製程式碼
最後在java中獲取物件
MenuItem item = menu.findItem(R.id.toolbar_delete); Button button = (Button) item.getActionView().findViewById(R.id.menu_button); button.setOnClickListener(view -> { Toast.makeText(MainActivity.this,"Button",Toast.LENGTH_SHORT).show(); }); 複製程式碼
注意:若呼叫 setSupportActionBar
,則在 onCreateOptionsMenu(Menu menu)
中獲取menu引用,否則直接 Menu menu = mToolbar.getMenu();
app:actionLayout

<item android:id="@+id/toolbar_delete" android:title="delete" android:icon="@drawable/ic_delete" app:actionLayout="@layout/menu_action" app:showAsAction="always"/> 複製程式碼
注意:menu_action佈局檔案的內容必須以RelativeLayout作為根容器佈局,否則,actionLayout 對應的檢視寬度不足以填充滿 Toolbar 或者說 ActionBar 的寬度,顯示效果如同設定 layout_width 屬性值為 wrap_content 一般。

注意:第二,actionLayout 屬性必須使用 app 作為名稱空間,如果使用 android 的話,會導致 menuItem 物件通過 getActionView() 始終獲取的物件為 null 。
最後在java中獲取物件
MenuItem item = menu.findItem(R.id.toolbar_delete); Button button = (Button) item.getActionView().findViewById(R.id.menu_button); button.setOnClickListener(view -> { Toast.makeText(MainActivity.this,"Button",Toast.LENGTH_SHORT).show(); }); 複製程式碼
注意:若呼叫 setSupportActionBar
,則在 onCreateOptionsMenu(Menu menu)
中獲取menu引用,否則直接 Menu menu = mToolbar.getMenu();
Fragment中使用
有時候需要在Fragment中使用Toolbar,比如Activity中不同的Tab顯示不同的Fragment,同時每個Tab的Toolbar標題、Menu均不相同,這時在Activity中使用同一個Toolbar就相當不方便了。我們可以在每個Fragment的佈局中新增各自的Toolbar,然後在Fragment中單獨控制。
與Activity中使用Toolbar有所不同。替換ActionBar時,需要給setSupportActionBar方法新增作用物件:
((AppCompatActivity)getActivity()).setSupportActionBar((Toolbar) mContentView.findViewById(R.id.tb_toolbar)); 複製程式碼
新增Options Menu時,需要額外呼叫setHasOptionsMenu(true);方法,確保onCreateOptionsMenu()方法得以呼叫,並且onCreateOptionsMenu()方法多了一個MenuInflater引數:
@Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.search, menu); } 複製程式碼
注意: MenuItem 的點選事件會先執行宿主 Activity 中的 onOptionsItemSelected 方法,然後再將事件傳遞到 Fragment 中。所以,如果需要覆蓋或者說遮蔽 Activity 的影響,需要在宿主 Activity 中修改該方法的返回值為 flase,如:
@Override public boolean onOptionsItemSelected(MenuItem item) { ... return false; } 複製程式碼