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 里的内容
<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>
</style>
然后记得在 onCreate 方法里,调用 setSupportActionBar(mToolbar);
讲完基本,现在来看看最简单的使用。
2.1 Navigation Button && Logo Image && Title and Subtitle
<android.support.v7.widget.Toolbar
android:background="@color/colorPrimary"
android:id="@+id/activity_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:navigationIcon="@drawable/ic_list"
app:logo="@drawable/ic_down"
app:title="Title"
app:titleTextColor="@android:color/white"
app:subtitle="subTitle"
app:subtitleTextColor="@android:color/white"
></android.support.v7.widget.Toolbar>
得到下面的效果:
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 文件。
<?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">
<!--说明
1.orderInCategory 表示显示的次序
2.showAsAction: never ifroom always
never 总是在 pop 菜单中显示
ifroom 如果有空间则在 actionbar 上显示,否则在 pop 菜单中显示
always 总是在 actionbar 上显示
-->
<item
android:title="收藏"
android:id="@+id/menu_action_item1"
android:icon="@drawable/ic_like"
android:orderInCategory="1"
app:showAsAction="never" />
<item
android:title="分享"
android:id="@+id/menu_action_item2"
android:icon="@drawable/ic_share"
android:orderInCategory="2"
app:showAsAction="always" />
<item
android:title="设置"
android:id="@+id/menu_action_item3"
android:orderInCategory="3"
android:icon="@drawable/ic_set"
app:showAsAction="never" />
</menu>
接下来在 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);
}
效果图:
效果图.gif这里我们可以看到这样几个问题:
- 1.pop 菜单弹出的时候挡住了 actionbar
- 2.其实菜单中的选项本来也是黑色的,演示不方便已经改成白色
- 3.右上角的图标颜色和其他的不统一
下面来看如何修改这几个问题:
- 前面两个问题可以通过 Toolbar 的 app:popupTheme="@style/CustomPopupTheme" 属性解决,在 res/value/style.xml 中增加 CustomPopupTheme 如下:
<!-- Toolbar ActionMenu 样式 -->
<style name="CustomPopupTheme" parent="ThemeOverlay.AppCompat.Light">
<item name="android:textColor">@android:color/white</item>
<item name="android:textSize">14sp</item>
<item name="android:colorBackground">@color/colorPrimary</item>
<!--overlapAnchor 是让 ActionMenu 不要盖住ToolBar-->
<item name="overlapAnchor">false</item>
</style>
GIF.gif
- 下面要修改右上角图标的颜色,我在网上一共找到三个属性
<!-- ActionMenu 图标颜色-->
<item name="android:actionMenuTextColor">#ffffff</item>
<item name="android:textColorSecondary">@android:color/white</item>
<item name="android:colorControlNormal">@android:color/white</item>
- 根据网上的资料显示,有放在 AppTheme 里面的,也有放在 CustomPopupTheme 里面的,几种方法我都试了一下,只有 textColorSecondary 属性放在 AppTheme 里是有效的。
- 其实最开始,我并没有考虑到利用 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 实现具体效果的时候遇到的问题。
谢谢观赏