引き出しを開くたびにActionBarのメニュー項目を非表示にするナビゲーション引き出しを実装しようとしています。
私はグーグルのドキュメントに従っていますが、それらのコードは期待される動作を生成しません。
http://developer.Android.com/training/implementing-navigation/nav-drawer.html
このコードを使用すると、引き出しが完全に開いたときにメニュー項目が非表示になり、引き出しが完全に閉じたときに表示されます。
ただし、Gmailアプリの動作は異なります。メニュー項目は、引き出しが開くとすぐに非表示になります。これは私が望む動作です。誰もこれを達成する方法を知っていますか?
ありがとう!
これを試しましたか:
invalidateOptionsMenu()
を使用します。onPrepareOptionsMenu(Menu menu)
の各メニュー項目を繰り返し、非表示にします。
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
// If the nav drawer is open, hide action items related to the content view
boolean drawerOpen = shouldGoInvisible;
hideMenuItems(menu, !drawerOpen);
return super.onPrepareOptionsMenu(menu);
}
private void hideMenuItems(Menu menu, boolean visible)
{
for(int i = 0; i < menu.size(); i++){
menu.getItem(i).setVisible(visible);
}
}
ナビゲーションドロワーがスライドした量の検出:
mDrawerLayout.setDrawerListener(new DrawerListener(){
float mPreviousOffset = 0f;
@Override
public void onDrawerClosed(View arg0) {
super.onDrawerClosed(arg0);
shouldGoInvisible = false;
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
@Override
public void onDrawerOpened(View arg0) {
super.onDrawerOpened(arg0);
shouldGoInvisible = true;
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
@Override
public void onDrawerSlide(View arg0, float slideOffset) {
super.onDrawerSlide(arg0, slideOffset);
if(slideOffset > mPreviousOffset && !shouldGoInvisible){
shouldGoInvisible = true;
invalidateOptionsMenu();
}else if(mPreviousOffset > slideOffset && slideOffset < 0.5f && shouldGoInvisible){
shouldGoInvisible = false;
invalidateOptionsMenu();
}
mPreviousOffset = slideOffset;
}
@Override
public void onDrawerStateChanged(int arg0) {
// or use states of the drawer to hide/show the items
}});
注:shouldGoInvisible
はクラスフィールドです。
ドロワーが画面に入ってアクションバーを復元するとすぐにアクションバーをオーバーライドし、ドロワーが表示されなくなった瞬間(2014年3月20日時点でのGmailの正確な動作)に次のコードを使用できます。
_mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close) {
@Override
public void onDrawerStateChanged(int newState) {
super.onDrawerStateChanged(newState);
boolean isOpened = mDrawerLayout.isDrawerOpen(mDrawerList);
boolean isVisible = mDrawerLayout.isDrawerVisible(mDrawerList);
if (!isOpened && !isVisible) {
if (newState == DrawerLayout.STATE_IDLE) {
// drawer just hid completely
restoreActionBar();
} else {
// } else if (newState == DrawerLayout.STATE_SETTLING) {
// drawer just entered screen
overrideActionBar();
}
}
}
private void restoreActionBar() {
getSupportActionBar().setTitle(mTitle);
supportInvalidateOptionsMenu();
}
private void overrideActionBar() {
getSupportActionBar().setTitle(mDrawerTitle);
supportInvalidateOptionsMenu();
}
};
// Set the drawer toggle as the DrawerListener
mDrawerLayout.setDrawerListener(mDrawerToggle);
_
必要に応じてrestoreActionBar()
およびoverrideActionBar()
メソッドを変更します。
スワイプとホームボタンを区別する必要はなく、スワイプの長さを測定する必要もありません。
引き出しリストビューを参照したくない場合は、代わりに次のコードを使用します。
_ boolean isOpened = mDrawerLayout.isDrawerOpen(GravityCompat.START);
boolean isVisible = mDrawerLayout.isDrawerVisible(GravityCompat.START);
_
XMLレイアウトで指定した内容に応じて、代わりに_GravityCompat.END
_を使用することもできます。
上記の例では、ナビゲーションドロワーの下のコンテンツに関連するアクションバー項目は非表示になりません。これを行うか、ドロワーが表示されているときに異なるアイコンセットを表示するには、ドロワーが手動で開かれたか閉じられたかを追跡する必要があります。
上記のコードに加えて、適切な保存/復元状態処理で_private boolean mDrawerVisible = false
_を宣言します。次に、mDrawerToggle
内部メソッドを次のように変更します。
_ private void restoreActionBar() {
getSupportActionBar().setTitle(mTitle);
mDrawerVisible = false;
supportInvalidateOptionsMenu();
}
private void overrideActionBar() {
getSupportActionBar().setTitle(mDrawerTitle);
mDrawerVisible = true;
supportInvalidateOptionsMenu();
}
_
最後に、onCreateOptionsMenu
で異なるメニューリソースを膨らませるか、onPrepareOptionsMenu
でmDrawerVisible
の値に基づいて異なるアクションを表示/非表示にします。
私はニコラに半分同意しますが、引き出しの状態が変わったときにアイコンを更新するだけで十分です
引き出しの状態を追跡するグローバル変数を作成します。
private int mDrawerState;
新しいDrawerListenerを設定します。
mDrawerLayout.setDrawerListener(new DrawerListener() {
@Override
public void onDrawerStateChanged(int state) {
mDrawerState = state;
invalidateOptionsMenu();
}
@Override
public void onDrawerSlide(View view, float slide) {
// TODO Auto-generated method stub
}
@Override
public void onDrawerOpened(View view) {
// TODO Auto-generated method stub
}
@Override
public void onDrawerClosed(View view) {
// TODO Auto-generated method stub
}
});
メニューの可視性を更新します。
boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawer);
for(int i=0;i<menu.size();i++){
// If the drawer is moving / settling or open do not draw the icons
menu.getItem(i).setVisible(mDrawerState!=DrawerLayout.STATE_DRAGGING &&
mDrawerState!=DrawerLayout.STATE_SETTLING && !drawerOpen);
}
この質問にはより良い解決策があります:
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
if (navigationDrawerFragment.isDrawerOpen()) {
menu.clear();
}
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if (!navigationDrawerFragment.isDrawerOpen()) {
// Only show items in the action bar relevant to this screen
// if the drawer is not showing. Otherwise, let the drawer
// decide what to show in the action bar.
showLocalContextActionBar();
return false;
}
return super.onCreateOptionsMenu(menu);
}
私は異なるコードを持っていますが、同じ解決策があります:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
hideMenuItems(menu, !mShouldGoInvisible);
return super.onCreateOptionsMenu(menu);
}
private void hideMenuItems(Menu menu, boolean visible){
for(int i = 0; i < menu.size(); i++){
menu.getItem(i).setVisible(visible);
}
}
そして
@Override
public void onNavigationDrawerListener(boolean opened, int position) {
if (opened){
mShouldGoInvisible = true;
invalidateOptionsMenu();
} else {
mShouldGoInvisible = false;
invalidateOptionsMenu();
}
}
@Laurence Dawsonが答えを取り、それを少し簡略化しました。このソリューションでは、クラスメンバーを使用する必要はありません。
onCreate()
の間にこのコードを実行します:
DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
drawerLayout.setDrawerListener(new DrawerLayout.DrawerListener() {
@Override
public void onDrawerSlide(View view, float v) {
invalidateOptionsMenu();
}
@Override
public void onDrawerClosed(View view) {
invalidateOptionsMenu();
}
@Override
public void onDrawerOpened(View view) {}
@Override
public void onDrawerStateChanged(int state) {}
});
そして、このメソッドをオーバーライドします:
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
boolean actionsVisibility = !drawerLayout.isDrawerVisible(Gravity.START);
for(int i=0;i<menu.size();i++){
menu.getItem(i).setVisible(actionsVisibility);
}
return super.onPrepareOptionsMenu(menu);
}
いくつかのメモ:
layout_gravity
はXMLでstart
に設定されます。すべてのメニュー項目を非表示にする場合は、単に次を使用します。
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
return showActionBarMenu; // boolean value, set it in drawer listeners as class variable
}
次に、各メニュー項目を表示する必要はありません。