Fragment是Android里面中一個(gè)非常靈巧的設(shè)計(jì),它可以看做ui模塊,由活動托管。熟練的使用它們能優(yōu)雅的實(shí)現(xiàn)很復(fù)雜的界面,而且用它們編寫UI界面,相對于用一個(gè)個(gè)Activity所消耗內(nèi)存少得多,而且切換很流暢,可以參考知乎客戶端。
但是,F(xiàn)ragment使用過程中會出現(xiàn)一些小問題,這里講如何在Fragment中添加menu。我們都知道在活動中添加menu只用編寫好menu,在onCreateOptionsMenu中加載,并在onOptionsItemSelected中處理點(diǎn)擊事件就可以了,按照這個(gè)流程先試下
首先編寫menu.xml
<?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">
<item android:id="@+id/item_setting"
android:icon="@drawable/ic_settings"
android:title="@string/setting"
app:showAsAction="always"/>
</menu>
這里只添加一個(gè)設(shè)置的menu item
然后要加載menu需要toolbar或actionbar,這里分兩種情況:
- 用Activity中actionbar或toolbar,在Fragment中不添加toolbar
只需在Activity中初始化好標(biāo)題欄(用toolbar時(shí)要調(diào)用setSupportActionBar),在fragment中
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_main,menu);
super.onCreateOptionsMenu(menu, inflater);
}
- 去除Activity中標(biāo)題欄,在Fragment中添加toolbar
在fragment中初始化標(biāo)題欄時(shí)要注意,fragment中沒有setSupportActionBar方法,也就是在標(biāo)題欄還是要交給托管其的活動來處理,標(biāo)題欄最終設(shè)置到window上,代碼如下
/**
* Fragment中初始化Toolbar
* @param toolbar
* @param title 標(biāo)題
* @param isDisplayHomeAsUp 是否顯示返回箭頭
*/
public void initToolbar(Toolbar toolbar, String title, boolean isDisplayHomeAsUp) {
AppCompatActivity appCompatActivity= (AppCompatActivity) getActivity();
appCompatActivity.setSupportActionBar(toolbar);
ActionBar actionBar = appCompatActivity.getSupportActionBar();
if (actionBar != null) {
actionBar.setTitle(title);
actionBar.setDisplayHomeAsUpEnabled(isDisplayHomeAsUp);
}
}
然后再調(diào)用onCreateOptionsMenu加載到toolbar上
運(yùn)行一下,你會發(fā)現(xiàn)兩種情況下menu都沒加載出來。原來要在fragment中加載menu還需在其onCreate中加一句 setHasOptionsMenu(true),用于讓活動知道有menu要加載
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
現(xiàn)在menu加載出來了

然后重寫onOptionsItemSelected處理點(diǎn)擊事件
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.item_setting:
SettingActivity.start(getContext());
return true;
default:
return super.onOptionsItemSelected(item);
}
}
現(xiàn)在就大功告成了嗎,然而運(yùn)行后會發(fā)現(xiàn)無論怎么點(diǎn)擊onOptionsItemSelected都沒被調(diào)用??梢栽賏ndroid training中找到原因
http://developer.android.com/guide/topics/ui/actionbar.html
Note: If you added the menu item from a fragment, via the Fragment class's onCreateOptionsMenu callback, then the system calls the respective onOptionsItemSelected() method for that fragment when the user selects one of the fragment's items. However the activity gets a chance to handle the event first, so the system calls onOptionsItemSelected() on the activity before calling the same callback for the fragment.
也就是說在雖然在fragment中重寫onOptionsItemSelected,但系統(tǒng)會在activity中先調(diào)用onOptionsItemSelected,而活動中默認(rèn)都消耗了點(diǎn)擊事件,fragment中因此無法處理點(diǎn)擊。所以要先在托管碎片的活動中講frament中處理的menu item返回false,讓點(diǎn)擊事件能穿到fragment的onOptionsItemSelected中
@Override
public boolean onOptionsItemSelected(MenuItem paramMenuItem) {
switch (paramMenuItem.getItemId()) {
case R.id.item_setting:
return false;
default:
return super.onOptionsItemSelected(paramMenuItem);
}
}
總結(jié)下
要在fragment添加menu需要以下步驟:
- 在fragment的onCreate中添加一句 setHasOptionsMenu(true);
- 如果用的是活動的標(biāo)題欄,只需在onCreateOptionsMenu中加載menu;如果用Fragment自己的toolbar需要先用活動初始化toolbar,然后再onCreateOptionsMenu
- 在活動中重寫onOptionsItemSelected,講需要在fragment中處理的menu item直接返回false,再在fragment的onOptionsItemSelected中處理