Navigation Drawerを使用する場合、Android開発者は、ActionBarにおいて、Navigation Drawerで表現される画面のみにNavigation Drawerの画像を表示し、その他の画面には従来のアップカラットを表示することを推奨しています。
詳細はこちらをご覧ください:
1つのアクティビティで複数のレベルのフラグメントを制御していますが、すべてのレベルでナビゲーションドロワー画像を表示および機能させることができます。
下位のフラグメントを作成するときに、ActionBarDrawerToggle
setDrawerIndicatorEnabled(false)
を呼び出すと、ナビゲーションドロワー画像が非表示になり、Upキャレットが表示されるようになります。
LowerLevelFragment lowFrag = new LowerLevelFragment();
//disable the toggle menu and show up carat
theDrawerToggle.setDrawerIndicatorEnabled(false);
getSupportFragmentManager().beginTransaction().replace(R.id.frag_layout,
lowFrag, "lowerFrag").addToBackStack(null).commit();
問題は、トップレベルのフラグメントに戻ったときに、元のナビゲーションドロワー画像の代わりにアップカラットがまだ表示されていることです。トップレベルのフラグメントのActionBarを更新して、Navigation Drawerのイメージを再表示する方法について、何か提案があれば教えてください。
他のフラグメントを置き換えるために新しいフラグメントを用意するときは、以下のようにDrawerToggle setDrawerIndicatorEnabled(false)
をセットします。
LowerLevelFragment lowFrag = new LowerLevelFragment();
//disable the toggle menu and show up carat
theDrawerToggle.setDrawerIndicatorEnabled(false);
getSupportFragmentManager().beginTransaction().replace(R.id.frag_layout,
lowFrag).addToBackStack(null).commit();
次に、onBackPressed
のオーバーライドで、以下のようにDrawerToggleをsetDrawerIndicatorEnabled(true)
に設定して、上記を元に戻しました。
@Override
public void onBackPressed() {
super.onBackPressed();
// turn on the Navigation Drawer image;
// this is called in the LowerLevelFragments
setDrawerIndicatorEnabled(true)
}
に
setHasOptionsMenu(true)を追加して、オプションメニューを設定できるようにした。また、アクションバーの <b></b> を有効にするために
setDisplayHomeAsUpEnabled(true)` をセットしています。
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// needed to indicate that the fragment would
// like to add items to the Options Menu
setHasOptionsMenu(true);
// update the actionbar to show the up carat/affordance
getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
}
次に、onOptionsItemSelected
で、が押されるたびに、アクティビティの onBackPressed()
を呼び出し、1階層上に移動してナビゲーションドロワーイメージを表示させます。
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Get item selected and deal with it
switch (item.getItemId()) {
case android.R.id.home:
//called when the up affordance/carat in actionbar is pressed
getActivity().onBackPressed();
return true;
…
}
下位のフラグメントを実装するために、新しいアクティビティで下位のフラグメントを実装するのではなく、既存のフラグメントを置き換えると書かれていますね。
その場合、バック機能を手動で実装する必要があると思います。ユーザーがバックを押したときに、スタックをポップするコードがあります(例:Activity::onBackPressed
オーバーライド内)。 つまり、どこでそれを行うにしても、 setDrawerIndicatorEnabled
を逆向きにすればよいのです。
DrawerToggleの状態に応じて、MainActivityでHomeアイテムの選択を処理するようにしてみてください。こうすれば、すべてのフラグメントに同じコードを追加する必要はありません。
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Only handle with DrawerToggle if the drawer indicator is enabled.
if (mDrawerToggle.isDrawerIndicatorEnabled() &&
mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle action buttons
switch (item.getItemId()) {
// Handle home button in non-drawer mode
case android.R.id.home:
onBackPressed();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
FOLLOW UP
dzeikei さんの解決策はすてきですが、フラグメントを使う場合、バックスタックが空になったときにドロワー表示を自動的に戻すように拡張することができます。
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Only handle with DrawerToggle if the drawer indicator is enabled.
if (mDrawerToggle.isDrawerIndicatorEnabled() &&
mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle action buttons
switch (item.getItemId()) {
// Handle home button in non-drawer mode
case android.R.id.home:
// Use getSupportFragmentManager() to support older devices
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.popBackStack();
// Make sure transactions are finished before reading backstack count
fragmentManager.executePendingTransactions();
if (fragmentManager.getBackStackEntryCount() < 1){
mDrawerToggle.setDrawerIndicatorEnabled(true);
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}
EDIT
JD(@JJD)さんの質問に対して。
フラグメントはアクティビティで保持/管理されます。上記のコードは、そのアクティビティで一度書かれますが、onOptionsItemSelected
のためのアップキャレットだけを処理します。
あるアプリでは、バックボタンが押されたときのアップキャレットの動作も処理する必要がありました。これは、onBackPressed
をオーバーライドすることで処理することができます。
@Override
public void onBackPressed() {
// Use getSupportFragmentManager() to support older devices
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.executePendingTransactions();
if (fragmentManager.getBackStackEntryCount() < 1){
super.onBackPressed();
} else {
fragmentManager.executePendingTransactions();
fragmentManager.popBackStack();
fragmentManager.executePendingTransactions();
if (fragmentManager.getBackStackEntryCount() < 1){
mDrawerToggle.setDrawerIndicatorEnabled(true);
}
}
};
onOptionsItemSelectedと
onBackPressed` の間でコードが重複していることに注意してください。これは、メソッドを作成して、両方の場所でそのメソッドを呼び出すことで回避できます。
また、executePendingTransactions
を2回追加していますが、これは私の場合必須で、そうしないとアップキャレットの動作がおかしくなることがありました。