继续Material系列,先从Toolbar讲起git
在使用ActionBar的时候,一堆的问题:这个文字能不能定制,位置能不能改变,图标的间距怎么控制神马的,由此暴露出了ActionBar设计的不灵活。
在上一篇中,咱们只是简单使用了AppCompatActivity,他使用的仍然是ActionBar
官方在21之后提供了ToolBar。
Toolbar之因此灵活,是由于它其实就是一个ViewGroup,咱们在使用的时候和普通的组件同样,在布局文件中声明。github
使用Toolbar时,若是单纯的看成控件来使用,主题是不须要单独设置的。
可是若是想用他来替代ActionBar,
那么须要配置为Theme.AppCompat.NoActionBar
主题,
或者在主题中加入app
<item name="windowActionBar">false</item> <item name="windowNoTitle">true</item>
(两个都必须有,上一篇已经提到没有windowNoTitle
时会报错)
这里推荐使用第一种方式。ionic
Toolbar由于常常被用来替代ActionBar,因此通常项目里都会抽取出来,以便include。
可能有人会说,既然仍是用来替换ActionBar,那我项目里直接不动ActionBar不就完了?
对,通常状况下是没有问题的,可是有些界面须要借助Toolbar灵活性的时候,你就被迫要换成Toolbar了。
先来看Toolbar经常使用代码:ide
include_toolbar.xml布局
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/colorPrimary" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" android:minHeight="?attr/actionBarSize" />
配置中须要注意的是theme和popupTheme,咱们来仔细看下,先从View的theme提及。
Android 5.0引入一个全新的特性,容许你对view设置theme,这种设置会影响控件及其包含的子控件。
使用AppCompat v22.1.x 后,也能够给你 layout 里的任意视图设置主题。
只要使用 android:theme
这个属性就好,新版本的兼容库能够在 compat 和 framework 之间无缝地切换功能。
这是由于有ContextThemeWrapper
类,这个类API v1的时候就有了。
他包裹(wrap)一个存在的Context(这里指你的Activity),以后覆盖(overlay)一个新的主题在当前Context的主题之上,这也是为何叫ThemeOverlay。
ThemeOverlay.AppCompat.Light.ActionBar
ThemeOverlay.AppCompat.Dark.ActionBar
在AppCompat v21里,提供了一个快速方便的方法设置Toolbar的主题,使用app:theme。
而新版本22.1.x中,AppCompat 容许对 Toolbar 使用android:theme
代替app:theme
。
最好的一点是:它会自动继承父视图的theme ,而且兼容全部APIv11以上的设备。
示例:
<Toolbar android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <!-- This TextView inherits its theme from the parent Toolbar --> <TextView android:text="I'm light!" /> </Toolbar>
对于运行 API v10 甚至更老的设备来讲,你也可使用android:theme
属性, 不过它不会继承父视图theme。
这就意味着你要么从新考虑你的布局,要么为每个子视图都设置上 android:theme 属性。(这样作效率真的很低)
总结一下:
android:theme
app:theme
有时候咱们有需求:
ActionBar文字是白的,ActionBar Overflow弹出的是白底黑字
让ActionBar文字是白的,那么对应的theme确定是Dark。
但是让ActionBar弹出的是白底黑字,那么须要Light主题。
这时候popupTheme就派上用场了。
<android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/colorPrimary" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" android:minHeight="?attr/actionBarSize" />
注意:
使用app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
而不是android:popupTheme
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.blah); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); }
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.blah); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); // Set an OnMenuItemClickListener to handle menu item clicks toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { // Handle the menu item return true; } }); // Inflate a menu to be displayed in the toolbar toolbar.inflateMenu(R.menu.your_toolbar_menu); }
不能够,这种方式是有问题的。
两个Toolbar放在布局中后,下面的Toolbar不能顶到最左边。
stackoverflow : How to center action menu on toolbar 中有详细的描述。
问题中给出了SplitToolbar
的解决方案,但我尝试后发现这种解决方案仍然有轻微的偏移。
Toolbar的layout_height属性,要用“?attr/actionBarSize”而不是“?android:attr/actionBarSize”,替换后可解决NavigationIcon不垂直居中的问题。
缘由是系统的actionBarSize比AppCompat中的要小。使用“?android:attr/actionBarSize”调用了较小的那个。
须要声明的是,这种方法更加简便一些,有无Toolbar都适合使用。(感谢dongorigin指正)
直接在AppCompatActivity或者ActionBarActivity中调用startSupportActionMode
启动便可。
注意这里的ActionMode是support包里的ActionMode。
这时若是你运行程序触发ActionMode,可能会看到ActionMode和ActionBar分立成两栏,并无浮在ActionBar上面。
解决的办法很简单,在主题中加入
<item name="windowActionModeOverlay">true</item>
便可。
有些同窗使用了Dark主题下的Toolbar,而且主题使用了Theme.AppCompat.Light.NoActionBar
,这时候会发现ActionMode是Light主题,很难看。
那么怎么能配置成Dark主题呢?
<item name="actionBarTheme">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item>
<item name="actionBarPopupTheme">@style/ThemeOverlay.AppCompat.Light</item>
<!--action Mode背景--> <item name="actionModeBackground">@color/theme_color_action_mode</item>
代码示例:
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); toolbar.startActionMode(mActionModeCallback)
注意这里的ActionMode是view包下的,不是support v7下的。
保证ActionMode浮在ActionBar上及ActionMode背景色替换与上面方式一致,这里再也不赘述,请参考上文。
能够看到,ActionMode开启时,顶部的Status Bar颜色也跟着改变了
这种功能Theme中并无提供属性来修改。
可是联想到入门篇提到的代码设置status bar颜色,这里就不难实现了。
代码共享下:
private int mOldStatusBarColor = -1; private void setActionModeStatusBarColor(int colorResId) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { mOldStatusBarColor = mActivity.getWindow().getStatusBarColor(); setStatusBarColorCore(mActivity.getResources().getColor(colorResId)); } } @TargetApi(Build.VERSION_CODES.LOLLIPOP) private void setStatusBarColorCore(int color) { mActivity.getWindow().setStatusBarColor(color); } private void resetStatusBarColor() { if (mOldStatusBarColor != -1 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){ setStatusBarColorCore(mOldStatusBarColor); mOldStatusBarColor = -1; } }
开启时调用set,销毁时调用reset便可。
P.S. : 上面的计数能够经过setTitle来完成。
保持Activity调起,使用android:windowActionModeOverlay
属性。
看似让ActionMode浮在了ActionBar上,但其实存在很大问题。
这种方式在4.4如下会使用Holo风格(overflow图标能够看出来,不是三个原点,是三个方块),且ActionMode比ActionBar小一些(能够看到蓝色底边是ActionBar)