首發(fā)于我的博客,轉(zhuǎn)載請注明作者和原文鏈接听盖。
在Material Design中杨拐,推薦使用Toolbar代替之前3.0中的Actionbar棕所,以提供更靈活的視圖展現(xiàn)。
使用AppCompatActivity.setSupportActionBar(Toolbar)
之后辨宠,Toolbar就可以接管Actionbar的功能遗锣,例如option menu。
實質(zhì)上繼承于ViewGroup嗤形,可以在標(biāo)題欄上顯示任意內(nèi)容,寬高也可以任意設(shè)置赋兵。
同時也預(yù)先提供了一些設(shè)置項:
設(shè)置導(dǎo)航按鈕(Navigation Button):
app:navigationIcon=""
toolbar.setNavigationIcon();
getSupportActionBar().setHomeAsUpIndicator();
設(shè)置Logo(Logo):
app:logo=""
toolbar.setLogo();
getSupportActionBar().setLogo();
設(shè)置標(biāo)題(Title):
app:title=""
toolbar.setTitle();
getSupportActionBar().setTitle();
設(shè)置副標(biāo)題(Subtitle):
app:subtitle=""
toolbar.setSubtitle();
getSupportActionBar().setSubtitle();
如果想要系統(tǒng)默認(rèn)的返回圖標(biāo):
XML:
app:navigationIcon="?attr/homeAsUpIndicator"
Java:
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
XML布局:activity_toolbar.xml
下面兩種方式还最,在表現(xiàn)形式上有一點點區(qū)別,作為AppBarLayout的子View時毡惜,在Toolbar的下方會有一條陰影拓轻。
方式一:
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
app:popupTheme="@style/AppTheme.PopupOverlay"
android:id="@+id/toolbar">
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
方式二:
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:background="?colorPrimary"
android:theme="@style/AppTheme.AppBarOverlay"
app:popupTheme="@style/AppTheme.PopupOverlay"
android:id="@+id/toolbar">
</android.support.v7.widget.Toolbar>
有幾點特別說明:
-
app:theme
設(shè)置Toolbar的樣式。 -
app:popupTheme
設(shè)置Toolbar的菜單彈窗的樣式经伙。
一般來講扶叉,View是不能設(shè)置theme的,但是Google提供了一部分特殊的ThemeOverlay樣式帕膜,這些主題可以給View設(shè)置theme枣氧。
上面設(shè)置給theme和popupTheme的兩個style定義自styles.xml中:
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
提供Toolbar黑底白字的樣式,Toolbar菜單彈窗白底黑字的樣式垮刹。
在Activity中使用:ToolbarActivity
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_toolbar);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
}
在Fragment中使用:ToolbarFragment
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_toolbar, container, false);
Toolbar toolbar = (Toolbar) rootView.findViewById(R.id.toolbar);
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
return rootView;
}
Options Menu
在res下創(chuàng)建menu目錄达吞,再創(chuàng)建toolbar.xml:
<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=".toolbar.ToolbarActivity">
<item
android:id="@+id/action_settings"
android:title="@string/action_settings"
app:showAsAction="never" />
</menu>
在Activity中創(chuàng)建Options Menu
創(chuàng)建Toolbar的Options Menu,以及監(jiān)聽Options Menu的點擊事件荒典。
如果調(diào)用過setSupportActionBar(toolbar);
酪劫,那就只需要重寫下面的方法:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.toolbar, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
default:
break;
}
return super.onOptionsItemSelected(item);
}
在Fragment中創(chuàng)建Options Menu
如果想讓Fragment中的onCreateOptionsMenu生效必須先調(diào)用setHasOptionsMenu方法。
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
同樣寺董,已經(jīng)設(shè)置過setSupportActionBar(toolbar);
覆糟,重寫如下方法:
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.toolbar, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
getActivity().finish();
return true;
default:
break;
}
return super.onOptionsItemSelected(item);
}
注意
-
導(dǎo)航按鈕的id
設(shè)置導(dǎo)航圖標(biāo)(NavigationIcon/HomeAsUpIndicator),其默認(rèn)id就是android.R.id.home遮咖。
-
menu重復(fù)顯示
系統(tǒng)會先執(zhí)行Activity中的onCreateOptionsMenu滩字,再執(zhí)行Fragment中的onCreateOptionsMenu。
如果Fragment和Activity都同時inflate了一個menu資源文件御吞,那么menu資源所包含的菜單會出現(xiàn)兩次麦箍。
一開始,在activity中menu是空的陶珠,當(dāng)調(diào)用了getMenuInflater().inflate(R.menu.main, menu)挟裂,menu中便有了菜單項。
而在執(zhí)行到Fragment的(Menu menu, MenuInflater inflater)時背率,activity的menu就傳遞下來话瞧,作為第一個參數(shù)嫩与。
activity和Fragment中的menu其實是一個對象寝姿。
那么當(dāng)存在一個Activity和多個Fragment交排,但又想顯示不同的Options Menu時,可以在Fragment的onCreateOptionsMenu中調(diào)用
menu.clear();
饵筑。@Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); menu.clear(); inflater.inflate(R.menu.toolbar, menu); }
-
menu事件重復(fù)響應(yīng)
用
menu.clear()
可以解決inflate同一個menu資源文件時埃篓,重復(fù)顯示的問題。但是如果Activity和Fragment都對該menu響應(yīng)的話根资,就會執(zhí)行兩次響應(yīng)事件架专。
事件的執(zhí)行順序同樣是顯示執(zhí)行Activity的onOptionsItemSelected,再執(zhí)行Fragment的onOptionsItemSelected玄帕。
所以部脚,如果業(yè)務(wù)上Activity具有更高的優(yōu)先級,可以通過
return true;
裤纹,攔截試圖傳遞到Fragment的事件委刘。但是如果Fragment具有更高的優(yōu)先級的,就無解了鹰椒。