欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Material Design(二)—— Toolbar的使用

程序员文章站 2022-05-30 23:07:00
...

基本使用

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);

其他属性
Material Design(二)—— Toolbar的使用

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