繼續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)