ToolBar比ActionBar更加可控,自由。因此,Google 逐漸使用ToolBar來代替ActionBar。 轉載請標明出處http://www.cnblogs.com/tangZH/p/7850572.html 使用ToolBar 1.要引入appCompat_v7支持 2.主題設置為N ...
ToolBar比ActionBar更加可控,自由。因此,Google 逐漸使用ToolBar來代替ActionBar。
轉載請標明出處http://www.cnblogs.com/tangZH/p/7850572.html
使用ToolBar
1.要引入appCompat_v7支持
2.主題設置為NoActionBar
在style.xml文件中
<style name="MyAppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!--ToolBar顏色-->
<item name="colorPrimary">@color/colorBlack</item>
<!--狀態欄顏色-->
<item name="colorPrimaryDark">@color/colorBlack</item>
<!--視窗的背景色-->
<item name="android:windowBackground">@color/colorWhite</item>
<!--add searchView-->
<item name="searchViewStyle">@style/MySearchView</item>
<item name="actionOverflowMenuStyle">@style/OverflowMenuStyle</item>
</style>
給應用設置該主題
上面的style中有兩個風格:
1、<item name="searchViewStyle">@style/MySearchView</item>是在toolbar上面添加搜索框,所以還要再聲明一個style,即搜索框的style。
//Android自帶的搜索框
<style name="MySearchView" parent="Widget.AppCompat.SearchView"/>
2、<item name="actionOverflowMenuStyle">@style/OverflowMenuStyle</item>是設置溢出菜單的風格。
<style name="OverflowMenuStyle" parent="Widget.AppCompat.Light.PopupMenu.Overflow">
<!--把該屬性改為false即可使menu位置位於toolbar之下-->
<item name="overlapAnchor">false</item>
//背景色
<item name="android:colorBackground">@android:color/holo_blue_dark</item>
//文字顏色
<item name="android:textColor">@android:color/white</item>
//溢出菜單寬度
<item name="android:dropDownWidth">wrap_content</item>
//溢出菜單高度
<item name="android:dropDownHeight">wrap_content</item>
</style>
如圖便可見溢出菜單,關於菜單配置接下來會講
記住別忘了還要gradle里聲明依賴
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:21.0.3'
}
界面佈局
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_height="?attr/actionBarSize"
android:layout_width="match_parent" >
</android.support.v7.widget.Toolbar>
請記得用 support v7 里的 toolbar,不然然只有 API Level 21 也就是 Android 5.0 以上的版本才能使用。
程式代碼:
toolbar=(Toolbar) findViewById(R.id.toolbar);
toolbar.setTitle("主標題");
toolbar.setSubtitle("副標題");
toolbar.setLogo(R.mipmap.ic_launcher);
setSupportActionBar(toolbar);//把toolbar當成actionBar使用
toolbar.setNavigationIcon(R.drawable.ab_android);
這邊要留意的是setNavigationIcon需要放在 setSupportActionBar之後才會生效。
菜單配置
<?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">
<item
android:id="@+id/action_search"
android:orderInCategory="80"
android:title="@string/tv_search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="ifRoom"
/>
<item
android:id="@+id/action_share"
android:orderInCategory="90"
android:title="@string/tv_share"
app:actionProviderClass="android.support.v7.widget.ShareActionProvider"
app:showAsAction="ifRoom"
/>
<item
android:id="@+id/action_error_ques"
android:orderInCategory="100"
android:title="@string/tv_error_ques"
app:showAsAction="never"
android:icon="@mipmap/error_prac_icon"
/>
<item
android:id="@+id/action_collected_ques"
android:orderInCategory="110"
android:title="@string/tv_collection_ques"
app:showAsAction="never"
android:icon="@mipmap/memu_colle_prac_icon"
/>
</menu>
結果圖:
我們來講解一下上面xml文件中的一些屬性:
- orderInCategory
- 設置菜單項的排列順序,必須設置大於等於0的整數值。數值小的排列在前,如果值相等,則按照xml中的順序展現。
- title
菜單項的標題。 - icon
菜單項的圖標。 - showAsAction
該屬性有五個值,可以混合使用。- always
總是顯示在Toolbar上。 - ifRoom
如果Toolbar上還有空間,則顯示,否則會隱藏在溢出列表中。 - never
永遠不會顯示在Toolbar上,只會在溢出列表中出現。 - withText
文字和圖標一起顯示。 - collapseActionView
聲明瞭這個操作視窗應該被摺疊到一個按鈕中,當用戶選擇這個按鈕時,這個操作視窗展開。一般要配合ifRoom一起使用才會有效。
- always
接下來在程式中重寫onCreateOptionsMenu,載入菜單
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.memu_prac_toolbar,menu);
return true;
}
菜單單擊事件
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.action_error_ques:
startActivity(new Intent(MainActivity.this, ErrorActivity.class));
break;
case R.id.action_collected_ques:
startActivity(new Intent(MainActivity.this, CollectedActivity.class));
break;
default:
return false;
}
return true;
}
有時候會出現一個棘手的問題,那就是溢出菜單沒法顯示圖標,我們可以用反射機制來解決該問題,代碼如下:
/**
* 運用反射機制解決toolBar溢出菜單無法顯示圖標的問題
* @param view
* @param menu
* @return
*/
@Override
protected boolean onPrepareOptionsPanel(View view, Menu menu) {
if (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) {
Log.e(getClass().getSimpleName(), "onMenuOpened...unable to set icons for overflow menu", e);
}
}
}
return super.onPrepareOptionsPanel(view, menu);
}
我們再假設一個場景:mainActivity裡面有一個ViewPager和一個toolbar,ViewPager裡面有幾個Fragment,當fragment切換的時候要動態改變toolbar的菜單,那麼我們應該怎麼做呢?
我們都知道,我們在建立actionbar或是toolbar的時候,都會預設的實現兩個方法,分別是onCreateOptionsMenu和onOptionsItemSelected,這兩個方法,前面的是建立菜單,後面的對選中的菜單進行操作。onCreateOptionsMenu只會在第一次初始化菜單時調用,其後就不在運行了,也就是說它只一次載入完之後,就不會再動了,所以我們沒法通過這個方法來改變toolbar的菜單。
Android給我們提供了一個onPrepareOptionsMenu(Menu menu)方法,我們可以在裡面動態改變菜單,然後通過判斷viewPager滑動到第幾頁,通過invalidateOptionsMenu()動態調用該方法。
/**
* 根據memuPosition的值來選擇載入的菜單
* @param menu
* @return
*/
@Override
public boolean onPrepareOptionsMenu(Menu menu)
{
menu.clear();
MenuInflater inflater=this.getMenuInflater();
switch (memuPosition)
{
case 0:
case 3:
inflater.inflate(R.menu.memu_prac_toolbar,menu);//答題界面的toolbar菜單
//如果只是想動態隱藏或者顯示菜單控制項的話可以用下麵的方法。
//menu.findItem(R.id.search_button).setVisible(true);
//menu.findItem(R.id.scan_button).setVisible(true);
//menu.findItem(R.id.setting_button).setVisible(false);
break;
case 1:
inflater.inflate(R.menu.memu_stu_toolbar,menu);//學習界面的toolbar菜單
break;
case 2:
inflater.inflate(R.menu.memu_forum_toolbar,menu);//論壇界面的toolbar菜單
break;
default:
break;
}
return super.onPrepareOptionsMenu(menu);
}
我們要先清除之前的菜單,不然它會在之前的菜單基礎上繼續添加。
在viewPager滑動的時候進行判斷,然後調用。
if(myViewPager.getCurrentItem()!=0)
{
myViewPager.setCurrentItem(0);
toolbar.setTitle(re.getString(R.string.tv_answer));
memuPosition=0; //標識位於第幾頁
invalidateOptionsMenu();//重新載入菜單
}
註意要調用invalidateOptionsMenu()或者supportInvalidateOptionMenu()方法。
既然已經用onPrepareOptionsMenu(Menu menu)來載入菜單了,那麼activity中的
@Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.memu_prac_toolbar,menu); return true; }
可以不寫,因為該方法便是來載入菜單的。
出了上面所將的這些,toolbar還有一些坑,那就是在fragment中使用的時候,繼續上面的場景,我們再增加一種場景,那就是需要在fragment中響應菜單的點擊事件,我們應該怎麼做呢?
我們可以在fragment裡面重寫onOptionsItemSelected(MenuItem item),例如下麵代碼:
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.action_vertical_arrangement:
//設置recycleView的佈局方式為豎直線性佈局
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
break;
case R.id.action_horizontal_arrangement:
//設置recycleView的佈局方式為網格佈局
recyclerView.setLayoutManager(new GridLayoutManager(getContext(),2));
break;
default:
return super.onOptionsItemSelected(item);
}
return true;
}
不過有一點需要很註意,那就是必須在onCreate里寫上setHasOptionsMenu(true),這樣子onOptionsItemSelected(MenuItem item)才有效。點擊事件是由Activity的onOptionsItemSelected(MenuItem item)傳進來的(事件分發)。
如果我們要在fragment中載入菜單,那麼可以在fragment中重寫onCreateOptionsMenu(Menu menu, MenuInflater inflater)
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
inflater.inflate(R.menu.memu_stu_toolbar,menu);
super.onCreateOptionsMenu(menu, inflater);
}
註意該方法與Activity中的public boolean onCreateOptionsMenu(Menu menu)是不一樣的,activity中的有返回值。一樣的必須在onCreate里寫上setHasOptionsMenu(true),fragment裡面的onCreateOptionsMenu(Menu menu, MenuInflater inflater)才會生效。
程式會先調用activity的public boolean onCreateOptionsMenu(Menu menu),再調用fragment里的onCreateOptionsMenu(Menu menu, MenuInflater inflater),如果fragment中沒有對menu進行清除,那麼fragment里的菜單會在Activity外的菜單基礎上添加上去。
以上便是本人就項目過程中遇到的問題對toolbar的總結,以後要是遇到其他問題會繼續補充。
轉載請標明出處https://i.cnblogs.com/EditPosts.aspx?postid=7850572