Toolbar是谷歌在2014年Google IO 大会上推出的一套全新的设计规范Material Design中的控件之一,主要是用来在android 5.0之后代替Android传统的标题栏ActionBar的,引入在android-support-v7兼容包下,使用ToolBar能实现和ActionBar一样的效果,并且ToolBar继承自ViewGroup,使用起来也是更加的灵活。
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary"
app:logo="@mipmap/ic_launcher"
app:title="标题"
app:titleTextColor="#fff"
app:subtitle="副标题"
app:subtitleTextColor="#fff"
app:navigationIcon="@drawable/ic_menu"
app:popupTheme="@style/toolBar_pop_item"
>
对导航图标navigationIcon设置点击监听:
mToolbar=findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);//利用Toolbar代替ActionBar
//设置导航Button点击事件
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this,"点击导航栏",Toast.LENGTH_SHORT).show();
}
});
如果你添加了 setSupportActionBar(toolbar); 这行代码,那么 toolbar.setNavigationOnClickListener监听方法,要放到其后面,否则点击事件,监听不到的。如果你用不到ActionBar的一些特性的话,建议setSupportActionBar(toolbar); 这行代码不用添加了。
关于菜单及自定义View的使用会在下面详细介绍。
传统的ActionBar在每次Android SDK版本更新时都会做一些改变,所以在不同的手机上往往会展示出不一样的效果,导致很严重的碎片化问题,GooGle官方为了解决这种碎片化问题在某次更新android-support-v7兼容包时引入了ToolBar,用来替代ActionBar,以达到不同版本展示效果的高度一致性。
1,首先上面也说了如果要实现标题栏,优先考虑使用ToolBar,可以有效的解决兼容性问题。
2,有很多人有这样的疑问,我自己写一个RelativeLayout或者其他什么布局都能实现标题栏,为什么非要用Toolbar呢?当然了首先它是GooGle官方推荐的标题控件,其次是使用ToolBar和其他MD设计风格的控件组合使用,能实现一些比较炫的效果,比如Toolbar+NestScrollView,Toolbar+DrawerLayout + NavigationView等等;
1,因为ToolBar位于V7包下,所以首先我们要确保应用引入了V7包,使用V7包下的ToolBar控件这样就可以兼容到5.0以下的版本。
2,设置项目的主题为NoActionBar。
3,在布局文件中使用:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:background="@color/colorAccent"
android:layout_width="match_parent"
app:navigationIcon="@drawable/ic_arrow_back_white"
app:title="我是ToolBar"
app:titleTextColor="#fff"
android:layout_height="?attr/actionBarSize">
</android.support.v7.widget.Toolbar>
</RelativeLayout>
上面ToolBar的高度可以给个固定值也可以使用?attr/actionBarSize指定为ActionBar的高度一致。
Activity中代码也很简单,初始化控件Toolbar,然后设置导航图标的点击事件监听,需要注意的是如果添加了 setSupportActionBar(toolbar); 这行代码,那么 toolbar.setNavigationOnClickListener监听方法,要放到其后面,否则点击事件,监听不到的,或者如果使用不到ActionBar的特性的话,这行代码我们完全可以不添加照样可以监听到导航按钮点击监听。
最终效果如下图:
1,首先在res目录下创建menu文件夹,然后定义一个toolbar_menu.xml文件,用于toolbar标题栏中各种action按钮的展示:
<?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"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<!--orderInCategory菜单项的优先级,也就是顺序,只能设置正整数,数值越大菜单项越靠前-->
<item
android:id="@+id/item1"
android:orderInCategory="100"
android:title="搜索"
android:icon="@drawable/icon_search"
app:showAsAction="ifRoom"
/>
<item
android:id="@+id/item2"
android:orderInCategory="100"
android:title="通知"
android:icon="@drawable/icon_notify"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/item3"
android:orderInCategory="100"
android:title="设置"
app:showAsAction="never"/>
<item
android:id="@+id/item4"
android:orderInCategory="100"
android:title="关于"
app:showAsAction="never"/>
</menu>
可以看出菜单中每个Item主要设置四个属性:id(用于监听区分),title(菜单名称),icon(图标),以及showAsAction(控制item在标题栏上的展示形式),默认Toolbar中显示的菜单项只会显示图标,设置的title不显示,但是我们长按该图标会发现title会显示在图标下方,另外溢出菜单中也只会显示菜单的title,不显示图标。
showAsAction属性我们主要关心如下三个取值:
1,always:表示永远显示在Toolbar中,如果屏幕空间不够则不显示。
2,ifRoom:如果toolbar上还有空间的话就会显示优先级高的菜单项在toolbar上,否则将剩下的显示在溢出菜单中 。
3,never:表示永远不显示在Toolbar中,而是一直显示在溢出菜单中。
2,在代码中关联Toolbar和menu菜单,并设置菜单的点击事件监听:
// 关联toolbar和menu,只需这一句代码菜单就可以正常显示了
toolBar.inflateMenu(R.menu.toolbar_menu);
// 手动设置溢出菜单项的图标
toolBar.setOverflowIcon(getResources().getDrawable(R.drawable.ic_menu_over_flow));
// 设置菜单点击事件监听
toolBar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()){
case R.id.item1:
Toast.makeText(ToolbarActivity.this, "菜单项1", Toast.LENGTH_SHORT).show();
break;
case R.id.item2:
Toast.makeText(ToolbarActivity.this, "菜单项2", Toast.LENGTH_SHORT).show();
break;
case R.id.item3:
Toast.makeText(ToolbarActivity.this, "菜单项3", Toast.LENGTH_SHORT).show();
break;
case R.id.item4:
Toast.makeText(ToolbarActivity.this, "菜单项4", Toast.LENGTH_SHORT).show();
break;
default:
break;
}
return false;
}
});
经过以上步骤后菜单就添加成功了,最终效果如下图:
因为在menu配置文件中我们设置了最后两个菜单项的showAsAction为never,所以默认会在标题栏的最右侧显示一个溢出菜单选项,该溢出菜单项的图标默认为灰色的竖排显示的三个小圆点,我们可以更改该图标,只要添加如下这句代码即可:
toolBar.setOverflowIcon(getResources().getDrawable(R.drawable.ic_menu_over_flow));
溢出菜单选项用来展示showAsAction属性为never和空间不足以展示的菜单项,当然了如果没有未被展示的item,这里就不会出现这个图标,然后我们点击溢出图标,系统默认的弹出样式是这样的:
首先我们发现溢出菜单弹出框中默认只显示菜单的title,不显示图标,如果我们想要溢出菜单的弹出框中除了能显示title外,还想显示图标,那么也是可以的,这里提供两种方案,具体请查看博客:https://blog.csdn.net/shangming150/article/details/77914110
其次我们可以看到默认的溢出菜单的弹出框样式非常丑,并且遮挡住了Toolbar标题栏,但是没关系,我们可以通过在布局文件中指定app:popupTheme="@style/menu_bg"属性来指定一个自定义的样式,至于这个样式具体能定义哪些内容,下面给出一个示例:
<!--自定义toolbar菜单样式-->
<style name="toolbarMenuStyle" parent="@style/Widget.AppCompat.PopupMenu.Overflow">
<!-- 是否覆盖锚点,默认为true,即盖住Toolbar -->
<item name="overlapAnchor">false</item>
<!-- 弹出层背景颜色 -->
<item name="android:popupBackground">@color/material_deep_teal_500</item>
<!-- 弹出层垂直方向上的偏移,负值会覆盖toolbar -->
<item name="android:dropDownVerticalOffset">5dp</item>
<!-- 弹出层水平方向上的偏移,即距离屏幕左边的距离,负值会导致右边出现空隙 -->
<item name="android:dropDownHorizontalOffset">-2dp</item>
<!--文字颜色-->
<item name="android:textColor">@color/white</item>
</style>
定义好样式后需要在app的主题中引用该样式,才能改变溢出框内的文字颜色,如下:
<!-- Base application theme. -->
<style name="AppTheme" parent="Base.AppTheme">
<!--指定toolbar弹出菜单样式-->
<item name="actionOverflowMenuStyle">@style/toolbarMenuStyle</item>
</style>
最后在toolbar中引用:
<android.support.v7.widget.Toolbar
android:background="@color/material_deep_teal_500"
android:id= "@+id/toolbar"
android:layout_width="match_parent"
app:popupTheme="@style/toolbarMenuStyle"
android:layout_height="?attr/actionBarSize">
</android.support.v7.widget.Toolbar>
这样溢出菜单的弹出框样式我们就修改完成了,具体再根据项目需求作相应的更改。
如果项目要求标题栏上的标题居中显示,通过查看查看api我们发现toolbar没有提供标题居中的方法,仅仅是提供了使其距左右,上下边距大小的方法。
不过不用担心,之前文中提到过Toolbar是一个ViewGroup,如果需要添加自定义View,只需要在Toolbar里面增加其子ViewGroup或者子View,然后设置居中即可。
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:gravity="center_vertical"
>
<ImageView
android:id="@+id/iv_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_back"
android:layout_centerVertical="true"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#fff"
android:text="标题"
android:textSize="18sp"
android:layout_centerHorizontal="true"
/>
</RelativeLayout>
</android.support.v7.widget.Toolbar>
上面的布局文件中没有使用默认的导航图标而是自定义了ImageView,如果想使用默认的导航图标也是可以的,布局修改如下即可:
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorAccent">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="标题"
android:textColor="@color/white"
android:textSize="22sp" />
</android.support.v7.widget.Toolbar>
注意此时 TextView 控件的宽和高都是自适应大小,java 代码中此行代码setSupportActionBar(toolbar);就不要添加了,否则就会显示不正常。
除非用到ActionBar的特性不然不推荐添加这行代码。
关于Toolbar就先介绍这么多,关于Toolbar和DrawerLyout实现侧滑动画效果,时间关系后续再来完善。