android - una - patrones de navegacion web
Ocultar los elementos del menú de la barra de acción cuando el cajón de navegación se desliza por cualquier cantidad (7)
Estoy intentando implementar un cajón de navegación que oculta los elementos del 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
Al usar este código, los elementos del menú se ocultan cuando el cajón se abre completamente , y se muestran cuando el cajón se cierra completamente.
Sin embargo, la aplicación de 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 como lograr esto?
¡Gracias!
¿Has probado esto?
- Use
invalidateOptionsMenu()
siempre que alterne el cajón de navegación, midiendo el desplazamiento deslizante. Iterar sobre cada elemento del menú en el menú de
onPrepareOptionsMenu(Menu menu)
y ocultarlo.@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 campo de clase.
Si desea anular la barra de acción tan pronto como el cajón entre en la pantalla y restaurar la barra de acción, el cajón del momento ya no se puede ver (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 restoreActionBar()
y overrideActionBar()
con sus necesidades.
No es necesario distinguir entre deslizar y botón de inicio y no es necesario medir las longitudes de barrido.
Variación
Si no desea hacer referencia a la vista de la 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 utilizar GravityCompat.END
lugar de lo que haya especificado en el diseño XML.
Editar - sobre acciones
El ejemplo anterior no oculta los elementos de la barra de acción 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 hacer 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 el manejo adecuado del estado de guardar / restaurar. Luego modifique los métodos internos de mDrawerToggle
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 un recurso de menú diferente o en onPrepareOptionsMenu
mostrar / ocultar diferentes acciones basadas en el valor de mDrawerVisible
.
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 no es necesario que esté visible de cada elemento del menú.
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();
}
}
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);
}
Tomé la respuesta de @Laurence Dawson y la simplifiqué un poco. Esta solución no requiere que se utilice 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 anular 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 supone que la vista asociada con NavigationDrawer tiene su
layout_gravity
configurado parastart
en XML. - No relacionado con la pregunta de OP, pero molesto: parece haber algún tipo de error que hace que el cajón se atasque en el camino. Si observa este comportamiento, aquí está la solución: error del cajón de navegación de Android usando la muestra
Yo estaba de acuerdo con Nikola, pero es suficiente para actualizar los iconos cuando el estado del cajón tiene
Cree 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);
}