Android ToolBar詳解

導讀

  • Toolbar是android L引入的一個新控件,繼承於ViewGroup,用於取代ActionBar,它提供了ActionBar類似的功能,但是更靈活

  • ToolBar不像ActionBar那麼固定,Toolbar更像是一般的View元素,可以被放置在view樹體系的任意位置,可以應用動畫,可以跟着ScrollView滾動,可以與佈局中的其他View交互

  • 當然,你還可以用Toolbar替換掉ActionBar,只需調用setSupportActionBar()

  • 爲了兼容更多的設備一般我們都是通過AppCompat中的android.support.v7.widget.Toolbar來使用Toolbar

  • 除此以外,ToolBar還支持android:elevation陰影屬性


ToolBar中的幾大子View

幾大子View

注意:

  1. 自定義的子View由於處於title,subTitle和menu之間,如果menu太多,或者Title,subTitle的字體太大或長度太長,自定義的子View可能被擠在中間而顯示不出來
  2. 自定義的子View 部分最左邊有間隙,如果要去掉,可以設置 contentInset 去掉

> 3. NavigationIcon 和 logo 不建議同時使用,不然logo 和 title,subtitle的間距會顯得比較小

ToolBar的使用方式:

  1. 將Toolbar當作actionbar來使用。這種情況一般發生在你想利用actionbar現有的一些功能(比如能夠顯示菜單中的操作項,響應菜單點擊事件,使用ActionBarDrawerToggle等),但是又想獲得比actionbar更多的控制權限。

  2. 將Toolbar當作一個獨立的控件來使用,這種方式又名Standalone。


ToolBar 使用步驟(獨立控件方式):

一.設置主題(主要是爲了隱藏ActionBar)

  1. ==常規來說==:直接用 Theme.AppCompat.Light.NoActionBar 即可

  2. 下面的方式主要解決部分項目既用Actionbar又用Toolbar

    • res\values\styles.xml (兼容低版本)
     <!--ToolbarActivity 的Theme-->
    <style name="AppTheme.NoActionBar">
        <!--隱藏ActionBar-->
        <item name="windowActionBar">false</item>
        <!--隱藏Title 標題欄(狀態欄)-->
        <item name="windowNoTitle">true</item>

        <!--Title,item字體顏色-->
        <item name="android:textColorPrimary">#f00fff</item>
        <!--窗體背景顏色-->
        <item name="android:windowBackground">@color/colorBackground</item>
        <!--底部操作欄顏色 API>21-->
        <item name="android:navigationBarColor">#33f000</item>
        <!--控件的默認顏色,如複選框未選中時的顏色,本文右上角的溢出菜單-->
        <item name="android:colorControlNormal">#ffffff</item>
    </style>

    <!--ToolbarActivity 彈出menu 的Theme-->
    <style name="AppTheme.menu1">
        <!--字體顏色-->
        <item name="android:textColor">#fff</item>
        <!--字體大小-->
        <item name="android:textSize">18sp</item>
        <!--&lt;!&ndash;背景色&ndash;&gt;-->
        <item name="android:colorBackground">#000</item>
        <!--選中顏色-->
        <item name="android:selectableItemBackground">@drawable/item_selector</item>

        <!-- 是否覆蓋錨點,默認爲true,即蓋住Toolbar -->
        <item name="overlapAnchor">false</item>

    </style>
  • res\values-v21\styles.xml (Android 5.0 的style,兼容高版本)
    <style name="AppTheme" parent="AppTheme.NoActionBar">
    </style>

注意:

  1. “windowActionBar”和”windowNoTitle”在AppCompatActivity中使用
  2. “android:windowActionBar”和”android:windowNoTitle”要在Activity中使用
  3. 主題調用:
    1. 清單文件對應activity便籤中調用 android:theme=”@style/AppTheme.NoActionBar”
    2. 全局調用,清單文件Application標籤中調用android:theme=”@style/AppTheme.NoActionBar”
    3. 對應控件調用 android:theme=”@style/AppTheme.NoActionBar”

二.設置控件

  1. 在佈局xml文件添加ToolBar控件(命名空間設置屬性)
<android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:clipToPadding="true"
        android:elevation="10dp"
        android:fitsSystemWindows="true"
        app:logo="@mipmap/ic_launcher"
        app:navigationIcon="@mipmap/ic_drawer_home"
        app:popupTheme="@style/AppTheme.menu1"
        app:subtitle="Subtitle"
        app:title="Title"
        >
        <!--自定義的子View-->
        <Button
            android:id="@+id/btn_user"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/colorAccent"
            android:text="@string/controls_toolbar"
            android:textColor="@color/colorBackground"/>
    </android.support.v7.widget.Toolbar>

注意:

ToolBar控件設置屬性有兩種方式:
- 第二種方式設置了屬性,第一種方式會無效
1. 代碼方式: (在Activity中初始化控件並設置參數)

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        toolbar.setNavigationIcon(R.mipmap.ic_drawer_home);//設置導航欄圖標
        toolbar.setLogo(R.mipmap.ic_launcher);//設置app logo
        toolbar.setTitle("Title");//設置主標題
        toolbar.setSubtitle("Subtitle");//設置子標題
        toolbar.inflateMenu(R.menu.base_toolbar_menu);//設置右上角的填充菜單
        toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
           ...
            }
        });
  1. 在ToolBar控件上直接設置:

    • 自定義命名空間才能設置成功,不然沒反應

      1. 先在根佈局設置命名空間: 如 xmlns:app=”http://schemas.android.com/apk/res-auto”

      2. 通過命名空間設置屬性:如 app:popupTheme=”@style/AppTheme.NoActionBar” (設置溢出菜單主題)

  1. 在res/menu下 添加action 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/action_search"
        android:icon="@mipmap/ic_search"
        android:title="@string/search_menu"
        app:showAsAction="ifRoom" />

    <item
        android:id="@+id/action_notification"
        android:icon="@mipmap/ic_notifications"
        android:title="@string/notification_menu"
        app:showAsAction="ifRoom" />

    <item
        android:id="@+id/action_item1"
        android:title="@string/item1_menu"
        app:showAsAction="never" />

    <item
        android:id="@+id/action_item2"
        android:title="@string/item2_menu"
        app:showAsAction="never" />
</menu>

三.控件調用

/**
 * ToolBar作爲獨立控件使用
 */
public class ToolBarActivity extends AppCompatActivity {
    private Button  btn;
    private Toolbar toolbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initView();

        initEvent();

    }

    private void initEvent() {
        toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                int menuItemId = item.getItemId();
                if (menuItemId == R.id.action_search) {
                    Toast.makeText(ToolBarActivity.this, R.string.search_menu, Toast.LENGTH_SHORT).show();

                } else if (menuItemId == R.id.action_notification) {
                    Toast.makeText(ToolBarActivity.this, R.string.notification_menu, Toast.LENGTH_SHORT).show();

                } else if (menuItemId == R.id.action_item1) {
                    Toast.makeText(ToolBarActivity.this, R.string.item1_menu, Toast.LENGTH_SHORT).show();

                } else if (menuItemId == R.id.action_item2) {
                    Toast.makeText(ToolBarActivity.this, R.string.item2_menu, Toast.LENGTH_SHORT).show();

                }
                return true;
            }
        });

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(ToolBarActivity.this, R.string.controls_toolbar, Toast.LENGTH_SHORT).show();
            }
        });
    }

    /**
     * 初始化界面
     */
    private void initView() {
        setContentView(R.layout.activity_toolbar);
        StatusBar.setTransparentStatusBar(this); //設置透明的狀態欄
        btn = (Button) findViewById(R.id.btn_user);
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        toolbar.inflateMenu(R.menu.toolbar_menu);//設置右上角的填充菜單(替換ActionBar方式不調用)

    }

效果圖:

效果圖


ToolBar 使用步驟(替換ActionBar方式):

一.設置主題

 <!--ToolbarActivity2 的Theme-->
    <style name="AppTheme.NoActionBar2">
        <!--隱藏ActionBar-->
        <item name="windowActionBar">false</item>
        <!--隱藏Title 標題欄(狀態欄)-->
        <item name="windowNoTitle">true</item>
        <!--Title,item字體顏色-->
        <item name="android:textColorPrimary">#ff0000</item>
        <!--窗體背景顏色-->
        <item name="android:windowBackground">@color/colorAccent</item>
        <!--底部操作欄顏色 API>21-->
        <item name="android:navigationBarColor">#4CAF50</item>
        <!--控件的默認顏色,如複選框未選中時的顏色,本文右上角的溢出菜單-->
        <item name="android:colorControlNormal">#00BCD4</item>

    </style>

二.設置控件

  1. 在佈局xml文件添加ToolBar控件
 <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:clipToPadding="true"
        android:elevation="10dp"
        android:fitsSystemWindows="true"
        >
        <!--自定義的子View-->
        <TextView
            android:id="@+id/tv_user2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/controls_toolbar"
            android:textColor="@color/colorBackground"/>
    </android.support.v7.widget.Toolbar>
  1. 在res/menu下 添加action 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/action_search"
        android:icon="@mipmap/ic_search"
        android:title="@string/search_menu"
        app:showAsAction="ifRoom" />

    <item
        android:id="@+id/action_notification"
        android:icon="@mipmap/ic_notifications"
        android:title="@string/notification_menu"
        app:showAsAction="ifRoom" />

    <item
        android:id="@+id/action_item1"
        android:title="@string/item1_menu"
        app:showAsAction="never" />

    <item
        android:id="@+id/action_item2"
        android:title="@string/item2_menu"
        app:showAsAction="never" />
</menu>

三.控件調用

/**
 * 將ToolBar當作actionBar使用
 */
public class ToolBar2Activity extends AppCompatActivity {
    private TextView mTextView;
    private Toolbar  toolbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initView();

        initEvent();

    }

    private void initEvent() {
        toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                int menuItemId = item.getItemId();
                if (menuItemId == R.id.action_search) {
                    Toast.makeText(ToolBar2Activity.this, R.string.search_menu, Toast.LENGTH_SHORT).show();

                } else if (menuItemId == R.id.action_notification) {
                    Toast.makeText(ToolBar2Activity.this, R.string.notification_menu, Toast.LENGTH_SHORT).show();

                } else if (menuItemId == R.id.action_item1) {
                    Toast.makeText(ToolBar2Activity.this, R.string.item1_menu, Toast.LENGTH_SHORT).show();

                } else if (menuItemId == R.id.action_item2) {
                    Toast.makeText(ToolBar2Activity.this, R.string.item2_menu, Toast.LENGTH_SHORT).show();

                }
                return true;
            }
        });

        mTextView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(ToolBar2Activity.this, R.string.controls_toolbar, Toast.LENGTH_SHORT).show();
            }
        });
    }

    /**
     * 初始化界面
     */
    private void initView() {
        setContentView(R.layout.activity_toolbar2);
        StatusBar.setTransparentStatusBar(this); //設置透明的狀態欄
        mTextView = (TextView) findViewById(R.id.tv_user2);
        toolbar = (Toolbar) findViewById(R.id.toolbar2);
        toolbar.setNavigationIcon(R.mipmap.ic_drawer_home);//設置導航欄圖標
        toolbar.setLogo(R.mipmap.ic_launcher);//設置app logo
        toolbar.setTitle("Title");//設置主標題
        toolbar.setSubtitle("Subtitle");//設置子標題

        setSupportActionBar(toolbar);
    }

    /**
     * ToolBar 替換ActionBar 方式要用這種方式實現Menu佈局,不然沒效果
     * @param menu
     * @return
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater=getMenuInflater();
        inflater.inflate(R.menu.toolbar_menu,menu);
        return super.onCreateOptionsMenu(menu);
    }
}

效果圖:

效果圖


Theme小擴展:

關於theme中幾個color字段的官方描述圖:

image

屬性 說明
colorPrimary 應用的主色調,ActionBar默認使用該顏色,ToolBar導航欄的底色
colorPrimaryDark 應用的主要暗色調,StatusBar狀態欄默認使用改顏色
colorAccent 控件選中的默認顏色,如EditText 的閃動光標
android:colorControlNormal 控件未選中時的默認顏色,如複選框
android:textColorPrimary 應用的主要文字顏色,ActionBar的標題文字默認顏色
android:textColorSecondary 輔助的文字顏色,一般比textColorPrimary的顏色弱一點,用於一些弱化的表示
android:windowBackground 窗體背景顏色,必須用color.xml定義的顏色
android:navigationBarColor 底部操作欄顏色 API>21
擴展屬性 擴展說明
statusBarColor 狀態欄顏色,默認使用colorPrimaryDark
colorForeground 應用的前景色,ListView的分割線,switch滑動區默認使用該顏色
colorBackground 應用的背景色,popMenu的背景默認使用該顏色
colorControlHighlight 控件按壓時的色調
colorControlActivated 控件選中時的顏色,默認使用colorAccent
colorButtonNormal 默認按鈕的背景顏色
editTextColor 默認EditView輸入框字體的顏色。
textColor Button,textView的文字顏色
textColorPrimaryDisableOnly RadioButton,checkbox等控件的文字
colorSwitchThumbNormal switch thumbs 默認狀態的顏色. (switch off)
 <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!--對應ActionBar顏色-->
        <item name="colorPrimary">@color/colorPrimaryDark</item>
        <!--對應狀態欄顏色-->
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <!--對應EditText 光標 顏色-->
        <item name="colorAccent">@color/colorAccent</item>
        <!--Title,item字體顏色-->
        <item name="android:textColorPrimary">#f00fff</item>
        <!--窗體背景顏色-->
        <item name="android:windowBackground">@color/colorBackground</item>
        <!--底部操作欄顏色 API>21-->
        <item name="android:navigationBarColor">#33f000</item>
        <!--控件的默認顏色,如複選框未選中時的顏色,本文右上角的溢出菜單-->
        <item name="android:colorControlNormal">#ffffff</item>
    </style>

測試效果圖:

image


源碼地址:

源碼下載


總結:

  1. 這次的學習,發現Theme和menu的理解有限,後續學習後文章補充這塊內容
  2. 測試的時候,發現6.0系統 selectableItemBackground設置Menu點擊背景顏色 沒反應,有解決方案的評論告知,謝了

樣式與主題詳解


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章