原生的Toolbar基本的功能样式已经在上节简单的说了一下,但是当前的样式并不满足我们的需要,因此这一节主要探索一下Toolbar的一些内容上调整的方法,比如Title位置居中的改变啊,PopuMenu菜单的显示位置等。
一:Toolbar的标题Title文字居中调整
关于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"
app:popupTheme="@style/AppTheme.PopupOverlay">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textSize="20sp"
android:text="标题"/>
</android.support.v7.widget.Toolbar>
这样虽然是实现了居中的效果,但是Toolbar的用法可不是这样的。下面,介绍另外一种标题居中的方法。先上效果图:
从效果图上看得出,文字已经居中显示了,那下面就是方法代码了:
private void setTitleCenter(Toolbar toolbar){
int childCount = toolbar.getChildCount();
for(int i = 0 ;i < childCount;i++){
View child = toolbar.getChildAt(i);
if(child instanceof TextView){
TextView childTitle = (TextView)child;
if(childTitle.getText().equals(toolbar.getTitle())){
int deviceWidth = getWindowManager().getDefaultDisplay().getWidth();
Paint p = childTitle.getPaint();
float textWidth = p.measureText(childTitle.getText().toString());
float tx = (deviceWidth - textWidth) / 2.0f - toolbar.getContentInsetLeft();
childTitle.setTranslationX(tx);
break;
}
}
}
}
基本的思想是这样的:首先获取Toobar的子view 的个数,然后循环获取子view,因为用来显示title的是一个TextView的控件,所以需要判断当前view 是否是TextView,由于Toolbar中还包含一个副标题,所以这里判断TextView的内容是否是一样的(注意:这里副标题和标题之间的文字不能相同暂时),这个时候如果判断通过则进入if语句中。首先获取屏幕的宽度,然后在获取文字的宽度,最后计算出title控件需要移动的距离,然后调用setTranslationX即可。
二:Toolbar中的PopuMenu菜单的显示位置
自定义溢出菜单之前,首先需要说明一点的是,当前的Activity的主题样式需要设置为”Theme.AppCompat.Light.NoActionBar”(或者”Theme.AppCompat.NoActionBar”),以及parent为它的也可以。如下代码:
<style name="AppTheme.NoActionBar" parent="Theme.AppCompat.Light.NoActionBar">
<!--修改Toolbar背景色-->
<item name="colorPrimary">@color/accent_material_dark</item>
<!--修改状态栏底色-->
<item name="colorPrimaryDark">@color/accent_material_light</item>
<!--修改虚拟按键导航栏背景色,只能在API v21 也就是 Android 5 以后的版本中使用,
因此要将之设定在 res/values-v21/styles.xml 里面才会起作用-->
<item name="android:navigationBarColor">@color/accent_material_light</item>
</style>
给Activity设置单独的主题样式:
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:logo="@mipmap/ic_launcher"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
然后,自定义PopouMenu的溢出样式如下:
<style name="OverflowMenuStyle" parent="@style/ThemeOverlay.AppCompat">
<!-- 是否覆盖overflow按钮,默认为true,即盖住Toolbar -->
<item name="overlapAnchor">false</item>
</style>
最后给Toolebar设置poputheme,如下:
<android.support.v7.widget.Toolbar
android:id="@+id/toolbarMain"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
app:popupTheme="@style/OverflowMenuStyle"
/>
这个时候效果图如下:
三:Toolbar内容调整
1.修改标题(“设置”)文字的颜色,在主题AppTheme.NoActionBar中添加如下代码即可。
<!--Toolbar标题颜色修改-->
<item name="android:textColorPrimary">@android:color/holo_blue_bright</item>
效果图:
从图上看出,修改的颜色不单单是标题的颜色,连点击overflowButton之后的PopuMenu弹框中的颜色也一起修改了。说明设置了这个属性之后这两个部分的文字颜色是一样的。
2.修改菜单栏MenuItem文字的颜色,即图中的”SETTINGS”文字
定义Toolbar菜单栏menu文字的样式如下:
<!--Toolbar中menu文字样式-->
<style name="ActionMenuTextStyle" parent="@style/ThemeOverlay.AppCompat.ActionBar">
<item name="actionMenuTextColor">@android:color/white</item>
</style>
定义好样式之后,设置app:theme=”@style/ActionMenuTextStyle”给Toolbar即可。如下代码:
<android.support.v7.widget.Toolbar
android:id="@+id/toolbarMain"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
app:popupTheme="@style/OverflowMenuStyle"
app:theme="@style/ActionMenuTextColor"
/>
然后看下效果图:
从图上看出,标题栏一行里面的“SETTINGS”文字颜色改为白色了额。
3.修改标题(“设置”)文字大小
颜色修改完了,现在看一下文字大小的修改。现在感觉文字有点小了,那好现在修改大一点的。现定义标题的样式如下:
<!--Toolbar标题样式-->
<style name="ToolbarTitle" parent="@style/TextAppearance.Widget.AppCompat.Toolbar.Title">
<item name="android:textSize">35sp</item>
</style>
然后设置此样式给Toolbar:app:titleTextAppearance=”@style/ToolbarTitle”,代码如下:
<android.support.v7.widget.Toolbar
android:id="@+id/toolbarMain"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
app:popupTheme="@style/OverflowMenuStyle"
app:theme="@style/ActionMenuTextStyle"
app:titleTextAppearance="@style/ToolbarTitle"/>
效果图看下:
文字大小变大了,比以前大多咧。
4.修改Overflow中,PopuMenu中文字大小
上面已经定义了一个OverflowMenuStyle样式的PopuMenu,所以只需要在添加一项即可。代码如下:
<style name="OverflowMenuStyle" parent="@style/ThemeOverlay.AppCompat">
<!-- 是否覆盖锚点,默认为true,即盖住Toolbar -->
<item name="overlapAnchor">false</item>
<item name="android:textSize">30sp</item>
</style>
由于前面已经给Toolbar设置了popuTheme样式,下面直接看效果图:
效果已经很明显了,文字被放大了。
5.单独给文字标题和Menu设置样式
从3和4中可以看出,只要设置不同的style就可以实现单独的样式设置。先改变如下:
<!--Toolbar中MenuItem文字样式-->
<style name="ActionMenuTextStyle" parent="@style/ThemeOverlay.AppCompat.ActionBar">
<item name="actionMenuTextColor">@android:color/white</item>
<item name="android:textSize">13sp</item>
</style>
<!--Toolbar标题样式-->
<style name="ToolbarTitle" parent="@style/TextAppearance.Widget.AppCompat.Toolbar.Title">
<item name="android:textSize">35sp</item>
<item name="android:textColor">@android:color/white</item>
</style>
<!--PopuMenu样式-->
<style name="OverflowMenuStyle" parent="@style/ThemeOverlay.AppCompat">
<!-- 是否覆盖锚点,默认为true,即盖住Toolbar -->
<item name="overlapAnchor">false</item>
<item name="android:textSize">30sp</item>
<item name="android:textColor">@android:color/holo_red_dark</item>
<item name="android:colorBackground">#5a5a5a</item>
</style>
样式改变如下:Toolbar标题栏中menu菜单的文字缩小,标题文字颜色变为白色,PopuMenu中文字变为红色,以及背景颜色现效果图如下:
6.修改PopuMenu中ListView的样式
发现PopuMenu中每一个MenuItem之间没有分割线,不爽!那么就自己定义一个样式,给它加上分割线,代码如下:
<!-- PopuMenu ListView Styles -->
<style name="PopupMenuListView" parent="@style/Widget.AppCompat.Light.ListView.DropDown">
<item name="android:divider">@android:color/white</item>
<item name="android:dividerHeight">1dp</item>
</style>
然后在“AppTheme.NoActionBar”Activity主题样式中添加如下代码:
<item name="android:dropDownListViewStyle">@style/PopupMenuListView</item>
效果图看下:
7.修改Menu的点击状态
有些时候吧,产品设计死脑筋,非得变一下点击的效果,所以这个时候原生的效果就不符合设计要求了,需要修改。那怎么改呢,先别急,先定义一个selector,如下:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/colorPrimaryDark" android:state_pressed="true" />
<item android:drawable="@color/colorPrimaryDark" android:state_focused="true"/>
<item android:drawable="@android:color/transparent"/>
</selector>
首先修改Toolbar中菜单栏MenuItem的点击效果,你只需要在“ActionMenuTextStyle”样式添加如下代码即可:
<item name="android:actionBarItemBackground">@drawable/menu_selector</item>
现看一下效果图:
从gif动画中看出,”SETTINGS”以及“OverflowButton”在点击的时候,会变为蓝色,而PopuMenu点击的时候颜色还是和以前的一样,没有修改。
那现在修改一下PopuMenu中Item点击的效果。你需要在“OverflowMenuStyle”样式中添加如下代码:
<item name="android:selectableItemBackground">@drawable/menu_selector</item>
现在再来看一下效果图:
加上如上代码之后,PopuMenu中item点击的效果也变了,如图所示。
8.给MenuItem设置icon
有些时候,menuItem中显示一下icon图标也是极好赏心悦目的。现改变menu布局如下:
<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="com.lingyun.toolbardemo.MainActivity">
<item
android:id="@+id/action_settings"
android:orderInCategory="100"
android:title="@string/action_settings"
app:showAsAction="always"
android:icon="@mipmap/ic_launcher"/>
<item
android:id="@+id/action_1"
android:orderInCategory="100"
android:title="@string/action_settings"
app:showAsAction="never"
android:icon="@mipmap/ic_launcher"/>
<item
android:id="@+id/action_2"
android:orderInCategory="100"
android:title="@string/action_settings"
app:showAsAction="never"
android:icon="@mipmap/ic_launcher"/>
</menu>
那么效果图来看下:
图上显示,Toolbar菜单栏中的MenuItem已经被icon图标替换,但是店址overflow之后的PopuMenu中并没有显示icon图标,怎么回事呢?这是官方的做法,默认只能显示文字而不能显示icon,但是觉得这样不美观啊,icon必须得显示出来。icon显示不显示是由MenuBuilder这个类的setOptionalIconsVisible方法来决定的,如果我们在PopuMenu被展开的时候给这个方法传入true,那么里面的每一个MenuItem对应的图标就都会显示出来了这个方法并没有对完开发,所以要调用此方法当然用到反射了。
(1)有的人可能把反射的代码卸载了onMenuOpened中,但是仍然可能是有问题的
@Override
public boolean onMenuOpened(int featureId, Menu menu) {
if (featureId == Window.FEATURE_ACTION_BAR && menu != null) {
if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
try {
Method m = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
m.setAccessible(true);
m.invoke(menu, true);
} catch (Exception e) {
}
}
}
return super.onMenuOpened(featureId, menu);
}
像我activity继承的是AppCompatActivity,所以,此方法行不通,在这就不贴图了。那把反射的地方换一下,通过重写onPrepareOptionsPanel方法来实现。
@Override
protected boolean onPrepareOptionsPanel(View view, Menu menu) {
if (menu != null) {
if (menu.getClass() == MenuBuilder.class) {
try {
Method m = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
m.setAccessible(true);
m.invoke(menu, true);
} catch (Exception e) {
e.printStackTrace();
}
}
}
return super.onPrepareOptionsPanel(view, menu);
}
看下效果图如下:
9.修改navigation icon的padding值
修改padding值,就需要在style.xml中修改;在此我们修改的是navigation的pading值:
(1)定义style
<style name="myToolbarNavigationButtonStyle" parent="@style/Widget.AppCompat.Toolbar.Button.Navigation">
<item name="android:minWidth">0dp</item>
<item name="android:padding">8dp</item>
<item name="android:scaleType">centerInside</item>
</style>
然后在“AppTheme.NoActionBar”Activity主题样式中添加如下代码:
<item name="toolbarNavigationButtonStyle">@style/myToolbarNavigationButtonStyle</item>
效果图就不贴了。
好了,到这里基本上的样式改变应该差不多都涉及到了。通过上面的探索,发现,针对不同的控件,会有单独的style样式供其设置来改变,就像ActionMenuTextStyle、ToolbarTitle、OverflowMenuStyle等,来改变相对应的控件的样式,剩下的得自己在探索了。
android:Toolbar用法探析(一):
http://blog.csdn.net/tabolt/article/details/51831930