Material Design - Toolbar

关键字:Toolbar、材料设计
项目地址:AboutMaterialDesign


一、从官网了解

链接:Toolbar
安卓 app 大多有标题栏这个 UI 功能,但是系统自带的 actionbar 已经没法满足日益进步的 UI 设计,为此在材料设计的支持包中,添加了 Toolbar 这个控件。Toolbar 可以作为一个普通的控件添加在任意视图层级中,同时也可以利用 setSupportedActionBar() 将其设置为 Activity 的 action bar。

Toolbar 提供了更加丰富的配置功能,在布局上从左到右主要有以下几点:

  • 1.A navigation button
  • 2.A branded logo image
  • 3.A title and subtitle
  • 4.One or more custom views
  • 5.An action menu

主要内容就是这些,下面都是一些方法和属性介绍,内容太多,就不再绘制表格了。

二、简单使用

首先,记得设置 AppTheme 为 NoActionBar,具体操作为更改 res/style/AppTheme 里的内容


然后记得在 onCreate 方法里,调用 setSupportActionBar(mToolbar);
讲完基本,现在来看看最简单的使用。

2.1 Navigation Button && Logo Image && Title and Subtitle

得到下面的效果:

Toolbar效果图
  • 1.左侧的 navigation button 一般用于打开侧边的菜单栏,类似于打开 DrawerLayout 的抽屉布局。它的点击事件在代码中可以通过
    mToolbar.setNavigationOnClickListener() 设置。
  • 2.logo 就是标题的小图标。
  • 3.title 和 subtitle 也可以很清楚地看到效果了,如果需要设置字体样式,title 可以通过 app:titleTextAppearance="" 设置,间距也可以通过 app:titleMargin="" 设置;subtitle 可以通过 app:subtitleTextAppearance="" 设置,不过间距好像没有 app:subtitleMargin="" 。

2.2 Custom View
View addView = LayoutInflater.from(mToolbar.getContext()).inflate(R.layout.snack_custom_img, null);
Toolbar.LayoutParams p = new Toolbar.LayoutParams( Toolbar.LayoutParams.WRAP_CONTENT,Toolbar.LayoutParams.WRAP_CONTENT, Gravity.RIGHT);
addView.setLayoutParams(p);
mToolbar.addView(addView);

通过上面的方法就可以向 Toolbar 中添加自定义的视图。默认 Gravity 为 CENTER_VERTICAL | START,这块代码主要可以看 Toolbar 的 onlayout 方法。

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    
    //...一些变量声明

    // Align views within the minimum toolbar height, if set.
    final int minHeight = ViewCompat.getMinimumHeight(this);
    final int alignmentHeight = minHeight >= 0 ? Math.min(minHeight, b - t) : 0;

    if (shouldLayout(mNavButtonView)) {
        ...
    }

    if (shouldLayout(mCollapseButtonView)) {
        ...
    }

    if (shouldLayout(mMenuView)) {
        ...
    }

    if (shouldLayout(mExpandedActionView)) {
        ...
    }

    if (shouldLayout(mLogoView)) {
        ...
    }

    if (layoutTitle) {
        ...
    }
    if (layoutSubtitle) {
        ...
    }

    if (layoutTitle || layoutSubtitle) {
        
        switch (mGravity & Gravity.VERTICAL_GRAVITY_MASK) {
            case Gravity.TOP:
                ...
                break;
            default:
            case Gravity.CENTER_VERTICAL:
                ...
                break;
            case Gravity.BOTTOM:
                ...
                break;
        }
        ...
    }

    // Get all remaining children sorted for layout. This is all prepared
    // such that absolute layout direction can be used below.

    addCustomViewsWithGravity(mTempViews, Gravity.LEFT);
    final int leftViewsCount = mTempViews.size();
    for (int i = 0; i < leftViewsCount; i++) {
        left = layoutChildLeft(mTempViews.get(i), left, collapsingMargins,
                alignmentHeight);
    }

    addCustomViewsWithGravity(mTempViews, Gravity.RIGHT);
    final int rightViewsCount = mTempViews.size();
    for (int i = 0; i < rightViewsCount; i++) {
        right = layoutChildRight(mTempViews.get(i), right, collapsingMargins,
                alignmentHeight);
    }

    // Centered views try to center with respect to the whole bar, but views pinned
    // to the left or right can push the mass of centered views to one side or the other.
    addCustomViewsWithGravity(mTempViews, Gravity.CENTER_HORIZONTAL);
    ...

    mTempViews.clear();
}

可以看到,Toolbar 依次放置完内部的控件后,开始根据 Gravity 放置自定义 View。其中 addCustomViewsWithGravity 方法主要功能是把相同 Gravity 的 View 依次取出放入 mTempViews,之后再根据规则进行放置。这里,代码用最简单的 ImageView 布局靠右演示。

customView.png

以上就是 customview 的全部内容,说到底这个东西方法简单,重在想象力和其他控件的综合使用。


2.3 ActionMenu

在 res/menu/ 目录下,新建一个以 menu 为根节点的 xml 文件。



    
    

    

    


接下来在 ToolbarActivity 中重写下面的几个方法:


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

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_action_item1:
                Log.i(TAG, "onMenuItemClick: like");
                makeText(ToolbarActivity.this, "like", Toast.LENGTH_SHORT).show();
                break;
            case R.id.menu_action_item2:
                Log.i(TAG, "onMenuItemClick: share");
                makeText(ToolbarActivity.this, "share", Toast.LENGTH_SHORT).show();
                break;
            case R.id.menu_action_item3:
                Log.i(TAG, "onMenuItemClick: setup");
                makeText(ToolbarActivity.this, "setup", Toast.LENGTH_SHORT).show();
                break;
        }
        return super.onOptionsItemSelected(item);
    }

效果图:

Material Design - Toolbar_第1张图片
效果图.gif

这里我们可以看到这样几个问题:

  • 1.pop 菜单弹出的时候挡住了 actionbar
  • 2.其实菜单中的选项本来也是黑色的,演示不方便已经改成白色
  • 3.右上角的图标颜色和其他的不统一

下面来看如何修改这几个问题:

  • 前面两个问题可以通过 Toolbar 的 app:popupTheme="@style/CustomPopupTheme" 属性解决,在 res/value/style.xml 中增加 CustomPopupTheme 如下:

    
    

Material Design - Toolbar_第2张图片
GIF.gif
  • 下面要修改右上角图标的颜色,我在网上一共找到三个属性

#ffffff
@android:color/white
@android:color/white
  • 根据网上的资料显示,有放在 AppTheme 里面的,也有放在 CustomPopupTheme 里面的,几种方法我都试了一下,只有 textColorSecondary 属性放在 AppTheme 里是有效的。
右上角图标变白.png
  • 其实最开始,我并没有考虑到利用 Theme 去更改,因为这种属性对与我们来说,找起来成本有点高。因此,最初的想法是更换图片:
mToolbar.setOverflowIcon(getResources().getDrawable(R.drawable.ic_more));//更改右上角图标
右上角图标变白.png

三、遇到的小问题

1.右上角 actionMenu 不显示

这个是因为有的手机自带了菜单键,系统中默认不显示那三个点的图标,因系统而异。最方便的解决办法是把手机的设备信息改为没有菜单键。

try {
    ViewConfiguration config = ViewConfiguration.get(this);
    Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
    if (menuKeyField != null) {
        menuKeyField.setAccessible(true);
        menuKeyField.setBoolean(config, false);
    }
} catch (Exception e) {
    e.printStackTrace();
}
参考链接:https://www.pocketdigi.com/20141024/1388.html

2.mToolbar.setNavigationOnClickListener 不起作用
把相关方法放在 setSupportedActionBar 之后


本来觉得一篇可以把这个结束,但是仔细实现起来发现 ActionMenu 的问题还是挺多的,因此会另起一篇,写写利用 ActionMenu 实现具体效果的时候遇到的问题。

谢谢观赏

你可能感兴趣的:(Material Design - Toolbar)