Masquer ActionBar MenuItems lors de la Navigation des glissades de tiroir pour n'importe quelle quantité

j'essaie de mettre en place un tiroir de Navigation qui cache les éléments du menu dans la barre d'action chaque fois que le tiroir est ouvert.

je suis la documentation de google, mais leur code ne produit pas le comportement attendu.

http://developer.android.com/training/implementing-navigation/nav-drawer.html

en utilisant ce code, les éléments du menu sont cachés lorsque le tiroir devient ouvert complètement , et affiché lorsque le tiroir devient complètement fermé.

cependant, L'application Gmail se comporte différemment. Les éléments du menu sont cachés dès que le tiroir s'ouvre de n'importe quel montant . C'est le comportement que je veux. Quelqu'un sait-il comment faire?

Merci!

28
demandé sur Nikola Despotoski 2013-08-09 00:10:36

7 réponses

avez-vous essayé ceci:

  1. utilisez invalidateOptionsMenu() chaque fois que vous basculez le tiroir nav, en mesurant l'offset coulissant.
  2. itérez chaque élément de menu dans onPrepareOptionsMenu(Menu menu) et cachez-le.

    @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);
    
        }
    }
    

Détection de combien la valeur liquidative de tiroir a slided:

     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

        }});

Note: shouldGoInvisible est le champ de classe.

47
répondu Nikola Despotoski 2013-12-27 22:39:01

si vous voulez outrepasser la barre d'action dès que le tiroir entre à l'écran et restaurer la barre d'action le tiroir moment n'est plus visible (exactement comment se comporte Gmail à partir du 20 mars 2014) , vous pouvez utiliser le code suivant:

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);

Modifier restoreActionBar() et overrideActionBar() méthodes selon vos besoins.

Il n'est pas nécessaire de distinguer entre les mouvements, et bouton home et pas besoin de mesurer balayage de longueurs.

Variation

si vous ne voulez pas consulter la liste des tiroirs, utilisez plutôt le code suivant:

    boolean isOpened = mDrawerLayout.isDrawerOpen(GravityCompat.START);
    boolean isVisible = mDrawerLayout.isDrawerVisible(GravityCompat.START);

vous pouvez utiliser GravityCompat.END à la place selon ce que vous avez spécifié dans la disposition XML.

Edit-actions concernant

l'exemple ci-dessus ne cache pas les éléments de la barre d'action pertinents au contenu sous le tiroir de navigation. Pour le faire ou montrer un ensemble différent d'icônes lorsque le tiroir est visible il faut savoir si le tiroir est ouvert ou fermé manuellement.

en plus du code ci-dessus, déclarez private boolean mDrawerVisible = false avec le traitement de sauvegarde/restauration de l'état approprié. Modifier ensuite mDrawerToggle méthodes internes comme suit:

  private void restoreActionBar() {
    getSupportActionBar().setTitle(mTitle);
    mDrawerVisible = false;
    supportInvalidateOptionsMenu();
  }

  private void overrideActionBar() {
    getSupportActionBar().setTitle(mDrawerTitle);
    mDrawerVisible = true;
    supportInvalidateOptionsMenu();
  }

enfin dans onCreateOptionsMenu gonfler différent menu ressource ou dans onPrepareOptionsMenu afficher/cacher différentes actions basées sur la valeur de mDrawerVisible .

5
répondu Eugen Pechanec 2014-09-23 17:49:24

Je suis à moitié D'accord avec Nikola mais il suffit de mettre à jour les icônes quand l'état du tiroir a

créer une variable globale pour garder la trace de l'état de tiroir:

private int mDrawerState;

Définir un nouveau 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
  }
});

mettre à jour le menu visibilité:

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);
}
2
répondu Ljdawson 2013-08-08 22:30:34

j'ai une meilleure solution pour cette question:

@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);
}
1
répondu GFPF 2015-06-25 20:59:06

si vous voulez cacher tous les éléments du menu, utilisez simplement:

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
    super.onPrepareOptionsMenu(menu);

    return showActionBarMenu; // boolean value, set it in drawer listeners as class variable
}

alors vous n'avez pas besoin de visible de chaque élément de menu.

0
répondu Cloudream 2013-10-14 06:06:36

j'ai pris la réponse de @Laurence Dawson et je l'ai un peu simplifiée. Cette solution n'exige pas l'utilisation de membres de la classe.

exécute ce code pendant 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) {}
    });

et remplacer cette méthode:

@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);
}

quelques notes:

  • l'implémentation ci-dessus suppose que la vue associée à NavigationDrawer a son layout_gravity défini à start en XML.
  • sans rapport avec la question de L'OP, mais ennuyeux: il semble y avoir une sorte de bug qui fait que le tiroir est coincé le long du chemin. Si vous observez ce comportement, voici la solution: Android drawer bug utilisant l'échantillon
0
répondu Vasiliy 2017-05-23 12:00:42

j'ai un code différent mais la même solution:

@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);
    }
}

et

 @Override
public void onNavigationDrawerListener(boolean opened, int position) {

    if (opened){
        mShouldGoInvisible = true;
        invalidateOptionsMenu();

    } else {
        mShouldGoInvisible = false;
        invalidateOptionsMenu();
    }
}
0
répondu Cabezas 2015-12-23 15:21:23