Ocultar los MenuItems de la barra de acción cuando el cajón de navegación se desliza por cualquier cantidad


Estoy tratando de implementar un Cajón de navegación que oculta los elementos de menú en la barra de acción cada vez que se abre el cajón.

Estoy siguiendo la documentación de Google, sin embargo, su código no produce el comportamiento esperado.

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

Usando este código, los elementos del menú se ocultan cuando el cajón se abre completamente, y se muestran cuando el cajón se vuelve completamente cerrado.

Sin embargo, la aplicación Gmail se comporta de manera diferente. Los elementos del menú se ocultan tan pronto como el cajón se abre por cualquier cantidad. Este es el comportamiento que quiero. ¿Alguien sabe cómo lograrlo?

Gracias!

Author: Nikola Despotoski, 2013-08-09

7 answers

¿has probado esto:

  1. Use invalidateOptionsMenu() cada vez que alterne el cajón de navegación, midiendo el desplazamiento deslizante.
  2. Itere sobre cada elemento del menú en onPrepareOptionsMenu(Menu menu) y escóndalo.

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

Detectando cuánto se ha deslizado el cajón de navegación:

     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

        }});

Nota: shouldGoInvisible es un campo de clase.

 47
Author: Nikola Despotoski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-27 22:39:01

Si desea anular la barra de acciones tan pronto como el cajón entre en la pantalla y restaurar la barra de acciones en el momento en que el cajón ya no sea visible (exactamente cómo se comporta Gmail a partir del 20 de marzo de 2014), puede usar el siguiente código:

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

Modifique los métodos restoreActionBar() y overrideActionBar() de acuerdo con sus necesidades.

No hay necesidad de distinguir entre los golpes y el botón de inicio y no hay necesidad de medir las longitudes de golpe.

Variación

Si no desea hacer referencia a la vista de lista de cajones, use el siguiente código en su lugar:

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

Es posible que desee usar GravityCompat.END en su lugar, dependiendo de lo que haya especificado en el diseño XML.

Editar-acerca de las acciones

El ejemplo anterior no oculta los elementos de la barra de acciones relevantes para el contenido debajo del cajón de navegación. Para hacerlo o mostrar un conjunto diferente de iconos cuando el cajón está visible, debe realizar un seguimiento de si el cajón se abre o se cierra manualmente.

Además del código anterior declare private boolean mDrawerVisible = false con la función de guardar / restaurar adecuada manejo estatal. Luego modifique mDrawerToggle los métodos internos de la siguiente manera:

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

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

Finalmente en onCreateOptionsMenu inflar diferentes recursos de menú o en onPrepareOptionsMenu mostrar/ocultar diferentes acciones basadas en el valor de mDrawerVisible.

 5
Author: Eugen Pechanec,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-23 17:49:24

Estoy medio de acuerdo con Nikola, pero basta con actualizar los iconos cuando el estado del cajón tiene

Crear una variable global para realizar un seguimiento del estado del cajón:

private int mDrawerState;

Establecer un nuevo 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
  }
});

Actualizar la visibilidad del menú:

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
Author: Ljdawson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-08 22:30:34

Tengo una mejor solución para esta pregunta:

@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
Author: GFPF,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-25 20:59:06

Si desea ocultar todos los elementos del menú, simplemente use:

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

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

Entonces usted no necesita visible de cada elemento de menú.

 0
Author: Cloudream,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-14 06:06:36

Tomé la respuesta de @Laurence Dawson y la simplifiqué un poco. Esta solución no requiere que se use ningún miembro de la clase.

Ejecuta este código durante 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) {}
    });

Y anula este método:

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

Algunas notas:

  • La implementación anterior asume que la vista asociada con NavigationDrawer tiene su layout_gravity establecido en start en XML.
  • No relacionado con la pregunta de OP, pero molesto: parece haber algún tipo de error que hace que el cajón atascado en el camino. Si observa este comportamiento, aquí está la solución: Error en el cajón de navegación de Android usando el ejemplo
 0
Author: Vasiliy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:00:42

Tengo un código diferente pero la misma solución:

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

Y

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

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

    } else {
        mShouldGoInvisible = false;
        invalidateOptionsMenu();
    }
}
 0
Author: Cabezas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-23 15:21:23