天天看點

Android基礎控件之Toolbar

文章目錄

      • 開個頭
        • 簡介
        • 使用Toolbar
        • 添加action button和overflowmenu
          • 1建立menu檔案
          • 2設定menu.xml檔案
            • 2.1沒調用setSupportAtionBar()
            • 2.2調用了setSupportActionBar()
          • 3.響應menu點選事件
            • 3.1沒調用setSupportAtionBar()
            • 3.2調用了setSupportAtionBar()
        • 細節調整
          • 1.關于傳回鍵
          • 2.關于标題
          • 3.關于overflow menu
      • 參考

開個頭

總結

Toolbar

基本用法

簡介

從 Android 3.0(API level11)開始,所有使用預設主題的 Activity 均使用

ActionBar

作為應用欄。不過,經過不同 Android 版本的演化,應用欄功能已逐漸添加到原生

ActionBar

中。是以,原生

ActionBar

的行為會随裝置使用的 Android 系統的版本而發生變化。相比之下,最新功能已添加到支援庫版本的

Toolbar

中,并且這些功能可以在任何能夠使用該支援庫的裝置上使用。

是以,您應使用支援庫的

Toolbar

類來實作 Activity 的應用欄。使用

support library

Toolbar

有助于確定您的應用在最大範圍的裝置上保持一緻的行為。例如,

Toolbar

小部件能夠在運作 Android 2.1(API 級别 7)或更高版本的裝置上提供 Material Design 體驗,但除非裝置運作的是 Android 5.0(API level 21)或更高版本,否則原生操作欄不會支援 Material Design。

使用Toolbar

  1. 首先導入V7包。現在的AS建立工程的時候,已經預設給我們導入了。
app build.gradle
	
	dependencies {
	   ...
	    implementation 'com.android.support:appcompat-v7:27.1.1'
	}
           
  1. 讓所有用到

    Toolbar

    的 Activity都繼承

    AppCompatActivity

public class MainActivity extends AppCompatActivity {
}
           
  1. 設定我們應用的主題為 appcompat 裡的

    NoActionBar

    主題,這樣就不會使用原生的

    ActionBar

    了。我經常用的就是這個

    Theme.AppCompat.Light.NoActionBar

<!-- Base application theme. -->
    <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>
    </style>
           
  1. xml

    布局檔案中添加

    Toolbar

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".MainActivity">
	<android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/colorPrimary"
        android:elevation="4dp">
    </android.support.v7.widget.Toolbar>
</LinearLayout>
           

Material Design 規範建議應用欄具有 4 dp 的仰角。

5. 在activity中調用

setSupportActionBar()

Toolbar

設定為 app bar,并且可以讓

Toolbar

使用

ActionBar

的特性。

//将 Toolbar設定為app bar
	setSupportActionBar(myToolbar);
	//請調用 Activity 的 getSupportActionBar() 方法。此方法将傳回對 appcompat ActionBar 對象的引用。
	//獲得該引用後,您就可以調用任何一個 ActionBar 方法來調整應用欄。例如,要隐藏應用欄,請調用 ActionBar.hide()。
	//ActionBar actionBar = getSupportActionBar();
           

看下效果

Android基礎控件之Toolbar

現在隻是效果出來,然後我們開始增磚添瓦。

添加action button和overflowmenu

1建立menu檔案

res/menu/

檔案夾下建立

main_toolbar_menu.xml

<?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">
    <!-- about showAsAction
           ifRoom: The action will display as a button,if there is enough room in app bar for it.
           If there is not enough room, the action will be send to the overflow menu.
           never: The action will always listed in the overflow menu.
    -->
    <item
        android:id="@+id/action_serch"
        android:icon="@android:drawable/ic_menu_search"
        android:title="one"
        app:showAsAction="ifRoom" />

    <item
        android:id="@+id/action_call"
        android:icon="@android:drawable/ic_menu_call"
        android:title="two"
        app:showAsAction="never" />
</menu>
           
2設定menu.xml檔案

2.1沒調用setSupportAtionBar()

如果沒有調用 setSupportActionBar()方法 。那麼很簡單直接用

Toolbar

inflateMenu()

方法。

2.2調用了setSupportActionBar()

如果調用了setSupportActionBar()方法。就是将

Toolbar

當做

ActionBar

,是以用如下方法

public class MainActivity extends AppCompatActivity{
	...
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main_toorbar_menu, menu);
        return true;
    }
}
           
3.響應menu點選事件

3.1沒調用setSupportAtionBar()

如果沒有調用

setSupportAtionBar()

我們要自己來處理menu的點選事件。

toolbar.setOnMenuItemClickListener(
        new Toolbar.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                // Handle menu item click event
                return true;
            }
});
           

3.2調用了setSupportAtionBar()

Toolbar

設定為

ActionBar

,我們處理方式如下

public class MainActivity extends AppCompatActivity{
	...
 	@Override
    public boolean onOptionsItemSelected(MenuItem item) {
    	switch (item.getItemId()) {
	        case R.id.action_serch:
	            showSnackBar(item.getTitle().toString());
	            return true;
	        case R.id.action_call:
	            showSnackBar(item.getTitle().toString());
	            return true;
	        default:
	            // If we got here, the user's action was not recognized.
	            // Invoke the superclass to handle it.
	            return super.onOptionsItemSelected(item);
	    }
    }
    //彈出一個snackBar
    public void showSnackBar(String string) {
        Snackbar.make(getDecorView(), string, Snackbar.LENGTH_LONG).show();
    }
    private View getDecorView() {
        return getWindow().getDecorView();
    }
}
           

建議調用

setSupportActionBar()

方法,因為設定了之後,

Toolbar

才會有material design效果。

Android基礎控件之Toolbar

細節調整

1.關于傳回鍵

在app bar 左邊添加傳回鍵圖檔,或者其他圖檔

//使用actionbar自帶的傳回鍵圖檔
	ActionBar actionBar = getSupportActionBar();
	actionBar.setDisplayHomeAsUpEnabled(true);
	//使用actionbar,自定義傳回鍵圖檔
	actionBar.setHomeAsUpIndicator(int redId);
	
	//使用toolbar自定義傳回鍵圖檔
	toolbar.setNavigationIcon(int redId);
           

如果是設定了

setDisplayHomeAsUpEnable(true)

,想改變傳回鍵圖檔的顔色,可以用如下方法

<resources>
    <!-- Base application theme. -->
    <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>
        <!--在主題中 設定 colorControlNomal參數即可改變,傳回鍵的顔色-->
        <item name="colorControlNormal">@color/white</item>
    </style>
</resources>
           
2.關于标題
//actioBar設定标題
	actionBar.setTitle();
	//actionBar設定子标題
	actionBar.setSubtitle();
	
	//toolbar設定标題
    toolbar.setTitle("MaterialDesign");
    //toolbar設定标題顔色
    toolbar.setTitleTextColor(Color.WHITE);
    //toolbar設定子标題
    toolbar.setSubtitle("sub title");
    //toolbar設定子标題顔色
    toolbar.setSubtitleTextColor(Color.BLACK);
           

設定标題的顔色和字型大小,還可以通過設定 style的方式來設定

<!--主标題-->
<style name="ToolbarTitle" parent="@style/TextAppearance.Widget.AppCompat.Toolbar.Title">
       <item name="android:textColor">#ffffff</item>
        <item name="android:textSize">15sp</item>
</style>

 <!--子标題-->
<style name="ToolbarSubtitle" parent="@style/TextAppearance.Widget.AppCompat.Toolbar.Subtitle">
        <item name="android:textColor">#ffffff</item>
        <item name="android:textSize">10sp</item>
</style>
           

設定完了之後,在布局檔案中給

Toolbar

設定對應的style就可以

<android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/colorPrimary"
        app:subtitleTextAppearance="@style/ToolbarSubtitle"
        app:titleTextAppearance="@style/ToolbarTitle"
        android:elevation="4dp">
	</android.support.v7.widget.Toolbar>
           

如果感覺以上的方法設定标題比較麻煩,可以完全定義一個

TextView

當做标題。

<android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/colorPrimary"
        android:elevation="4dp">
        
        <TextView
            android:id="@+id/tvTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:singleLine="true"
            android:text="title"
            android:textColor="#FFFFFF"
            android:textSize="18sp" />
    </android.support.v7.widget.Toolbar>
           

用此方式設定标題的時候要注意,如果調用了

setSupportActionBar()

方法設定了

Toolbar

,要調用如下方法來禁用使用appNamae來作為預設标題

//actionbar預設會将appName設定為标題,以下是不讓actionbar的預設标題展示。我們自已定一個TextView作為标題來維護
actionBar.setDisplayShowTitleEnabled(false);
           
3.關于overflow menu

Toolbar

的action button 隻顯示圖示還可以接受,而overflow menu裡面的item 隻顯示文字有時會讓你很難受。那麼如何讓overflow menu裡的item同時顯示圖示和文字呢。因為系統沒有暴露這個方法,我們隻能通過反射的方法來解決,如下。

@Override
    public boolean onMenuOpened(int featureId, Menu menu) {
        if (menu != null) {
            if ("MenuBuilder".equalsIgnoreCase(menu.getClass().getSimpleName())) {
                try {
                    @SuppressLint("PrivateApi")
                    Method method = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
                    method.setAccessible(true);
                    method.invoke(menu, true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return super.onMenuOpened(featureId, menu);
    }
           

細心的同學還會發現,overflow menu 點開的時候,會覆寫

Toolbar

.解決方法如下

<!--toolbar overflow menu 下拉風格-->
    <style name="OverflowMenu" parent="Base.Widget.AppCompat.PopupMenu.Overflow">
        <!--下拉框 不是從狀态欄開始,而是從toolbar底部開始-->
        <item name="overlapAnchor">false</item>
    </style>
    
 	定義好了style之後,在布局檔案裡面,給Toolbar設定overflow的style
	<android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/OverflowMenu"
        android:elevation="4dp">
	</android.support.v7.widget.Toolbar>
           

最後是加上了傳回鍵,自定義了标題欄,優化了overflow menu之後的效果圖

Android基礎控件之Toolbar

參考

google官方文檔 add the app bar

Stack Overflow 關于toolbar.inflateMenu()方法的問題

如果錯誤,歡迎指正!