Material Design(二)—— Toolbar的使用

基本使用

1. 引入Toolbar

添加v7依賴包
implementation 'com.android.support:appcompat-v7:27.0.3'

指定沒有Actionbar的主題,在values/styles/文件夾中修改爲NoActionBar
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">

這個AppTheme在Application指定爲整個APP的主題,如果你想要單獨指定Activity的主題,可以新建一個style,在AndroidManifest中指定Activity的對應主題style。

在xml文件中添加Toolbar控件

<android.support.v7.widget.Toolbar
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

theme – @style/ThemeOverlay.AppCompat.Dark.ActionBar單獨指定Toolbar主題爲深色主題,那麼字體默認就爲淺色(白色)
popupTheme – @style/ThemeOverlay.AppCompat.Light單獨指定popup菜單爲淺色主題,因爲前面指定toolbar主題爲深色主題,默認菜單爲深色不好看。

2. 代碼中進行相關設置

在Activity 中設置setSupportActionBar(),設置Toolbar爲Actionbar,使得可以通過Actionbar的API來對Toolbar進行操作。

mToolbar = findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);

對導航鍵進行設置圖標及監聽:
有兩種方式
(1)使用Toolbar的API

toolbar.setNavigationIcon();
toolbar.setNavigationOnClickListener();

(2)使用Actionbar的API

getSupportActionBar().setHomeAsUpIndicator();
getSupportActionBar.setDisplayHomeAsUpEnable();
onOptionItemSelect() { android.R.id.home} 

Title 標題設置

//主標題
toolbar.setTitle("Title");
toolbar.setTitleTextColor(Color.GREEN);

//副標題
toolbar.setSubtitle("Sub Title");
toolbar.setSubtitleTextColor(Color.RED);

Toolbar默認的標題是在左側,如果需要居中的標題,只需要在Toolbar中添加一個居中的TextView即可

    <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.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

        <!--添加子控件-->
        <TextView
            android:id="@+id/tv_center_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Center Title"
            android:layout_gravity="center"
            style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"/>

    </android.support.v7.widget.Toolbar>

記得將自有的Title隱藏

getSupportActionBar().setDisplayShowTitleEnabled(false);

其他屬性

Menu菜單設置

在res文件夾的menu文件夾下添加添加menu文件menu_toolbar

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/backup"
        android:icon="@drawable/ic_backup"
        android:title="Backup"
        app:showAsAction="collapseActionView"/>
    <item
        android:id="@+id/delete"
        android:icon="@drawable/ic_delete"
        android:title="Delete"
        app:showAsAction="ifRoom"/>
    <item
        android:id="@+id/settings"
        android:icon="@drawable/ic_settings"
        android:title="Settings"
        app:showAsAction="never"/>
</menu>

填充Menu,並對menu的響應進行設置

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.toolbar_menu, menu);
        return true;
    }


    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                Toast.makeText(this, "You click HomeAsUp", Toast.LENGTH_SHORT).show();
                break;
            case R.id.backup:
                Toast.makeText(ToolbarActivity.this, "click backup", Toast.LENGTH_SHORT).show();
                break;
            case R.id.delete:
                Toast.makeText(ToolbarActivity.this, "click delete", Toast.LENGTH_SHORT).show();
                break;
            case R.id.settings:
                Toast.makeText(ToolbarActivity.this, "click settings", Toast.LENGTH_SHORT).show();
                break;
            default:
        }
        return true;
    }

動態隱藏MenuItem:
getToolbar().getMenu().findItem(R.id.menu_refresh).setVisible(false);

Action View 及 Action Provider
ActionView
(1) Menu中可以添加ActionView,通過app:actionViewClass指定ActionView,ActionView也可以爲自定義的一些View,這裏指定爲SearchView

<item android:id="@+id/action_search"
     android:title="@string/search"
     android:icon="@drawable/ic_search"
     app:showAsAction="ifRoom|collapseActionView"
     app:actionViewClass="android.support.v7.widget.SearchView" />

也可以在onCreateOptionsView或代碼中的其他地方獲取到menuItem設置ActionView

getToolbar().getMenu().findItem(R.id.menu_refresh).setActionView(refreshActionView);

(2) 獲取ActionView
MenuItemCompat.getActionView(menuItem);

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main_activity_actions, menu);    
   MenuItem searchItem = menu.findItem(R.id.action_search);  
    SearchView searchView =
             (SearchView)MenuItemCompat.getActionView(searchItem);  
    // Configure the search info and add any event listeners...      
    return super.onCreateOptionsMenu(menu); 
}

(3) 響應action view的擴展,設置監聽
• onMenuItemActionCollapse()
• onMenuItemActionExpand()
當SearchView摺疊和擴展時的響應事件,代碼如下:

@Override
public boolean onCreateOptionsMenu(Menu menu) { 
     getMenuInflater().inflate(R.menu.options, menu);    
     // Define the listener    
    OnActionExpandListener expandListener = new OnActionExpandListener() {            
        @Override   
        public boolean onMenuItemActionCollapse(MenuItem item) {   
            // Do something when action item collapses      
             return true;     //Return true to collapse action view   
        }
        @Override  
        public boolean onMenuItemActionExpand(MenuItem item) {   
             // Do something when expanded   
             return true;      // Return true to expand action view  
        }   
};
// Get the MenuItem for the action item   
MenuItem actionMenuItem = menu.findItem(R.id.myActionItem);    
// Assign the listener to that action item    
MenuItemCompat.setOnActionExpandListener(actionMenuItem, expandListener);    
// Any other things you have to do when creating the options menu…    
return true;  
}

(4)讓自定義ActionView與普通MenuItem表現一致
在自定義View的xml佈局中設置style爲
style="@style/Widget.AppCompat.ActionButton"

(5) 直接在Menu中指定actionLayout

<item
        android:id="@+id/search2"
        android:icon="@drawable/ic_search"
        android:title="Search"
        app:showAsAction="always"
        app:actionLayout="@layout/action_layout" />

R.layout.action_layout

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent">
    <EditText
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

注意事項:
一、R.layout.action_layout 必須以 RelativeLayout 作爲根容器佈局,否則,actionLayout 對應的視圖寬度不足以填充滿 Toolbar 或者說 ActionBar 的寬度,顯示效果如同設置 layout_width 屬性值爲 wrap_content 一般;
二、actionLayout 屬性必須使用 app 作爲命名空間,如果使用 android 的話,會導致 menuItem 對象通過 getActionView() 始終獲取的對象爲 null 。

2.Action Provider:
下面聲明一個ShareActionProvider,這是一種在支持庫中定義的允許當前應用與其他應用分享數據的控件,和action view差不多,直接貼代碼:

在Fragment中使用

如果同一個Activity中不同Fragment的標題,Menu等不一樣時,需要在不同Fragment在分別定義Toolbar
在Fragment替換ActionBar時,需要給setSupportActionBar方法添加作用對象:

((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);

在Fragment中使用時,需要調用setHasOptionsMenu(true);確保onCreateOptionsMenu()方法得以調用,並且onCreateOptionsMenu()方法多了一個MenuInflater參數:

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
    inflater.inflate(R.menu.menu_toolbar, menu);
}

MenuItem 的點擊事件會先執行 Activity 中的 onOptionsItemSelected 方法,然後再將事件傳遞到 Fragment 中。如果需要覆蓋或者說屏蔽 Activity 的影響,需要在 Activity 中修改該方法的返回值爲 false

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    return false;
}

一些注意點:

1. 不顯示ActionBar還有另外兩種設置方法

(1) 可以直接在activity中設置
activity.supportRequestWindowFeature(Window.FEATURE_NO_TITLE) 去掉了默認的ActionBar(注意,我的BaseActivity是繼承了AppCompatActivity的,如果是繼承Activity就應該調用requestWindowFeature(Window.FEATURE_NO_TITLE))

(2) 在res/values/style.xml 中Activity或App對應的style(或繼承新建一個style)添加兩個屬性:

<!--將ActionBar隱藏,這裏使用ToolBar-->
<item name="windowActionBar">false</item>
<!-- 使用 API Level 22以上編譯的話,要拿掉前綴字android,以兼容低版本 -->
<item name="windowNoTitle">true</item>

2.如果不使用setSupportActionBar(),設置菜單還有另外一種方式:

    //如果設置了setSupportActionBar(),以下菜單設置將不起作用,顯示不出來
    //只能使用onCreateOptionsMenu和onOptionItemSelect
    toolbar.inflateMenu(R.menu.toolbar_menu);
    toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
        @Override
        public boolean onMenuItemClick(MenuItem item) {
            switch (item.getItemId()) {
                case R.id.backup:
                    Toast.makeText(ToolbarActivity.this, "click backup", Toast.LENGTH_SHORT).show();
                    break;
                case R.id.delete:
                    Toast.makeText(ToolbarActivity.this, "click delete", Toast.LENGTH_SHORT).show();
                    break;
                case R.id.settings:
                    Toast.makeText(ToolbarActivity.this, "click settings", Toast.LENGTH_SHORT).show();
                    break;
                default:
            }
            return true;
        }
    });

3.如何設置菜單字體顏色
在style文件中,指定android:textColorPrimary的值,指定此style爲菜單主題,設置Toolbar的app:popupTheme。

   <!--設置菜單字體顏色-->
    <style name="AppTheme.ToolBar" parent="ThemeOverlay.AppCompat.Light">
        <item name="android:textColorPrimary">@color/color_red</item>
    </style>

refer:
http://yifeng.studio/2016/10/12/android-toolbar/
https://www.jianshu.com/p/12570217636c

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