Establecer elemento seleccionado en Android BottomNavigationView
(16)
Agregue
android:enabled="true"
a BottomNavigationMenu Items.
Y luego establezca
bottomNavigationView.setOnNavigationItemSelectedListener(mListener)
y
bottomNavigationView.setOnNavigationItemSelectedListener(mListener)
como seleccionado haciendo
bottomNavigationView.selectedItemId = R.id.your_menu_id
Estoy usando el nuevo
android.support.design.widget.BottomNavigationView
de la biblioteca de soporte.
¿Cómo puedo configurar la selección actual del código?
Me di cuenta de que la selección vuelve a cambiar al primer elemento, después de girar la pantalla.
Por supuesto, también ayudaría, si alguien pudiera decirme, cómo "guardar" el estado actual de
BottomNavigationView
en la función
onPause
y cómo restaurarlo en
onResume
.
¡Gracias!
Ahora es posible desde la versión
setSelectedItemId()
llamar a
setSelectedItemId()
/ o /
Cometí un error en Google sobre el hecho de que no hay una forma confiable de seleccionar la página en BotViewNavigationView: https://code.google.com/p/android/issues/detail?id=233697
NavigationView aparentemente tuvo un problema similar, que solucionaron al agregar un nuevo método setCheckedItem ().
Desde la API 25.3.0 se introdujo el método
setSelectedItemId(int id)
que le permite marcar un elemento como seleccionado como si hubiera sido tocado.
De documentos:
Establece la ID del elemento del menú seleccionado. Esto se comporta igual que tocar un elemento.
Ejemplo de código:
BottomNavigationView bottomNavigationView;
bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottomNavigationView);
bottomNavigationView.setOnNavigationItemSelectedListener(myNavigationItemListener);
bottomNavigationView.setSelectedItemId(R.id.my_menu_item_id);
IMPORTANTE
DEBE haber agregado todos los elementos al menú y configurar el Listener antes de llamar a setSelectedItemId para que BottomNavigationView pueda ejecutar el comportamiento del código correspondiente. Si llama a setSelectedItemId antes de agregar los elementos del menú y configurar el oyente, no sucederá nada.
Esto probablemente se agregará en las próximas actualizaciones. Pero mientras tanto, para lograr esto puedes usar la reflexión.
Cree una vista personalizada que se extienda desde BottomNavigationView y acceda a algunos de sus campos.
public class SelectableBottomNavigationView extends BottomNavigationView {
public SelectableBottomNavigationView(Context context) {
super(context);
}
public SelectableBottomNavigationView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SelectableBottomNavigationView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void setSelected(int index) {
try {
Field f = BottomNavigationView.class.getDeclaredField("mMenuView");
f.setAccessible(true);
BottomNavigationMenuView menuView = (BottomNavigationMenuView) f.get(this);
try {
Method method = menuView.getClass().getDeclaredMethod("activateNewButton", Integer.TYPE);
method.setAccessible(true);
method.invoke(menuView, index);
} catch (SecurityException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}
Y luego úselo en su archivo de diseño xml.
<com.your.app.SelectableBottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:itemBackground="@color/primary"
app:itemIconTint="@drawable/nav_item_color_state"
app:itemTextColor="@drawable/nav_item_color_state"
app:menu="@menu/bottom_navigation_menu"/>
Para hacer clic programáticamente en el elemento BottomNavigationBar que necesita usar:
View view = bottomNavigationView.findViewById(R.id.menu_action_item);
view.performClick();
Esto organiza todos los artículos con sus etiquetas correctamente.
Parece estar arreglado en SupportLibrary 25.1.0 :) Editar: Parece arreglado que el estado de la selección se guarda al girar la pantalla.
Por encima de API 25, puede usar setSelectedItemId (menu_item_id) pero bajo API 25 debe hacer de manera diferente, Menú de usuario para obtener el identificador y luego establecer Chequeado en Elemento específico verificado
Puedes probar el método performClick:
View view = bottomNavigationView.findViewById(R.id.YOUR_ACTION);
view.performClick();
Si no quieres modificar tu código. Si es así, te recomendé que pruebes BottomNavigationViewEx 。
Solo necesita reemplazar llamar a un método
setCurrentItem(index);
y
getCurrentItem()
。
Simplemente agregue otra forma de realizar una selección programáticamente: esta es probablemente la intención en primer lugar o tal vez esto se agregó más adelante.
Menu bottomNavigationMenu = myBottomNavigationMenu.getMenu();
bottomNavigationMenu.performIdentifierAction(selected_menu_item_id, 0);
performIdentifierAction
toma una identificación de elemento de
Menu
y una bandera.
Vea la documentation para más información.
La reflexión es mala idea.
Dirígete a esta gist . Hay un método que realiza la selección pero también invoca la devolución de llamada:
@CallSuper
public void setSelectedItem(int position) {
if (position >= getMenu().size() || position < 0) return;
View menuItemView = getMenuItemView(position);
if (menuItemView == null) return;
MenuItemImpl itemData = ((MenuView.ItemView) menuItemView).getItemData();
itemData.setChecked(true);
boolean previousHapticFeedbackEnabled = menuItemView.isHapticFeedbackEnabled();
menuItemView.setSoundEffectsEnabled(false);
menuItemView.setHapticFeedbackEnabled(false); //avoid hearing click sounds, disable haptic and restore settings later of that view
menuItemView.performClick();
menuItemView.setHapticFeedbackEnabled(previousHapticFeedbackEnabled);
menuItemView.setSoundEffectsEnabled(true);
mLastSelection = position;
}
Para aquellos que todavía usan SupportLibrary <25.3.0
No estoy seguro de si esta es una respuesta completa a esta pregunta, pero mi problema fue muy similar: tuve que procesar presionar el botón
back
y llevar al usuario a la pestaña anterior donde estaba.
Entonces, tal vez mi solución sea útil para alguien:
private void updateNavigationBarState(int actionId){
Menu menu = bottomNavigationView.getMenu();
for (int i = 0, size = menu.size(); i < size; i++) {
MenuItem item = menu.getItem(i);
item.setChecked(item.getItemId() == actionId);
}
}
Tenga en cuenta que si el usuario presiona otra pestaña de navegación
BottomNavigationView
no borrará el elemento seleccionado actualmente, por lo que debe llamar a este método en
onNavigationItemSelected
después de procesar la acción de navegación:
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.some_id_1:
// process action
break;
case R.id.some_id_2:
// process action
break;
...
default:
return false;
}
updateNavigationBarState(item.getItemId());
return true;
}
Con respecto al almacenamiento del estado de instancia, creo que podría jugar con el mismo
action id
de
action id
de la vista de navegación y encontrar la solución adecuada.
private void setSelectedItem(int actionId) {
Menu menu = viewBottom.getMenu();
for (int i = 0, size = menu.size(); i < size; i++) {
MenuItem menuItem = menu.getItem(i);
((MenuItemImpl) menuItem).setExclusiveCheckable(false);
menuItem.setChecked(menuItem.getItemId() == actionId);
((MenuItemImpl) menuItem).setExclusiveCheckable(true);
}
}
El único ''menos'' de la solución es usar
MenuItemImpl
, que es ''interno'' a la biblioteca (aunque público).
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bottomNavigationView.setOnNavigationItemSelectedListener(this);
Menu menu = bottomNavigationView.getMenu();
this.onNavigationItemSelected(menu.findItem(R.id.action_favorites));
}
bottomNavigationView.setSelectedItemId(R.id.action_item1);
donde
action_item1
es la ID del elemento del menú.