阅读 939

Toolbar使用总结

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 的使用

1、更改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>
复制代码

2、在布局文件中添加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:titleTextAppearance="@style/Toolbar.TitleText"
        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>
复制代码

Toolbar.TitleText:

<!--Toolbar标题文字大小-->
<style name="Toolbar.TitleText" parent="TextAppearance.Widget.AppCompat.Toolbar.Title">
    <item name="android:textSize">15sp</item>
</style>
复制代码

3、在java中获取toolbar并设置属性

Toolbar特殊需求使用

1、 更改溢出菜单文字颜色

指定MyToolbarTheme(如上),添加:

<item name="android:textColor">@color/colorAccent</item>

2、 更改toolbar菜单文字大小,包括溢出菜单上的,和显示上的

  • 指定MyToolbarTheme(如上),添加:

<item name="android:textSize">25sp</item>

  • Toolbar标题文字大小

<!--Toolbar标题文字大小-->
<style name="Toolbar.TitleText" parent="TextAppearance.Widget.AppCompat.Toolbar.Title">
    <item name="android:textSize">15sp</item>
</style>
复制代码

3、更改toolbar上的菜单显示文字颜色

指定MyToolbarTheme(如上),添加: <item name="android:actionMenuTextColor">@color/colorPrimaryDark</item>

4、设置Menu窗口不覆盖Toolbar视图

指定MyToolbarTheme(如上),添加: <item name="overlapAnchor">false</item>

5、设置title与navigationIcon的间隔

指定MyToolbarTheme(如上),添加:

<item name="contentInsetStart">0dp</item>
<item name="contentInsetLeft">0dp</item>
<item name="contentInsetStartWithNavigation">0dp</item>
复制代码

6、设置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>
复制代码

7、标题居中

在Toolbar里面放置一个TextView控件作为居中的标题来使用,再将Toolbar的Title隐藏起来即可实现Toolbar标题居中的效果

若有使用setSupportActionBar(),则调用getSupportActionBar().setDisplayShowTitleEnabled(false);隐藏标题;若没设置,只要toolbar不设置title即可

8、让菜单同时显示图标和文字

只对setSupportActionBar起作用

    // 让菜单同时显示图标和文字
    @SuppressWarnings("PrivateApi")
    @Override
    public boolean onMenuOpened(int featureId, Menu menu) {
        if (menu != null) {
            if (menu.getClass().getSimpleName().equalsIgnoreCase("MenuBuilder")) {
                try {
                    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);
    }
复制代码

ActionMenuView

菜单默认在最右边,使用ActionMenuView可更改菜单显示位置,并可以动态删除添加菜单

1、在toolbar中增加ActionMenuView

2、在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"
        android:orderInCategory="100"
        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();

结合searchView

Toolbar 结合SearchView

app:actionLayout

<item
    android:id="@+id/toolbar_delete"
    android:title="delete"
    android:icon="@drawable/ic_delete"
    android:orderInCategory="100"
    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;
}
复制代码

参考链接

  1. Material Design 之 Toolbar
  2. MaterialDesign 之 SearchView 全面解锁
  3. Android Toolbar,你想知道的都在这里了
关注下面的标签,发现更多相似文章
评论