Définir l’élément sélectionné dans Android BottomNavigationView

J’utilise le nouveau android.support.design.widget.BottomNavigationView de la bibliothèque de support. Comment puis-je définir la sélection actuelle à partir du code? Je me suis rendu compte que la sélection repasse au premier élément après avoir fait pivoter l’écran. Bien entendu, si quelqu’un pouvait me dire comment sauvegarder l’état actuel du BottomNavigationView dans la fonction onPause et comment le restaurer dans onResume .

Merci!

À partir de l’API 25.3.0, la méthode setSelectedItemId(int id) été introduite pour vous permettre de marquer un élément comme sélectionné comme s’il était tapé.

De docs:

Définissez l’ID de l’élément de menu sélectionné. Cela se comporte de la même manière que taper sur un object.

Exemple de code:

 BottomNavigationView bottomNavigationView; bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottomNavigationView); bottomNavigationView.setOnNavigationItemSelectedListener(myNavigationItemListener); bottomNavigationView.setSelectedItemId(R.id.my_menu_item_id); 

IMPORTANT

Vous DEVEZ avoir déjà ajouté tous les éléments au menu et définir l’écouteur avant d’appeler setSelectedItemId afin que BottomNavigationView puisse exécuter le comportement du code correspondant. Si vous appelez setSelectedItemId avant d’append les éléments de menu et de définir l’écouteur, rien ne se produira.

Pour cliquer par programme sur l’élément BottomNavigationBar à utiliser:

 View view = bottomNavigationView.findViewById(R.id.menu_action_item); view.performClick(); 

Cela arrange tous les articles avec leurs étiquettes correctement.

Pour ceux qui utilisent encore SupportLibrary <25.3.0

Je ne suis pas sûr que ce soit une réponse complète à cette question, mais mon problème était très similaire – je devais traiter en back bouton et amener l’utilisateur à l’onglet précédent où il était. Donc, peut-être que ma solution sera utile pour quelqu’un:

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

Gardez à l'esprit que si l'utilisateur appuie sur un autre onglet de navigation, BottomNavigationView ne supprime pas l'élément actuellement sélectionné. Vous devez donc appeler cette méthode dans votre onNavigationItemSelected après le traitement de l'action de navigation:

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

En ce qui concerne la sauvegarde de l'état de l'instance, je pense que vous pouvez jouer avec le même action id de la vue de navigation et trouver la solution appropriée.

Il est maintenant possible depuis la version 25.3.0 d’appeler setSelectedItemId() \ o /

Cela sera probablement ajouté dans les prochaines mises à jour. Mais en attendant, pour y parvenir, vous pouvez utiliser la reflection.

Créez une vue personnalisée à partir de BottomNavigationView et accédez à certains de ses champs.

 public class SelectableBottomNavigationView extends BottomNavigationView { public SelectableBottomNavigationView(Context context) { super(context); } public SelectableBottomNavigationView(Context context, AtsortingbuteSet attrs) { super(context, attrs); } public SelectableBottomNavigationView(Context context, AtsortingbuteSet 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(); } } } 

Et puis utilisez-le dans votre fichier de mise en page XML.

  

Essayez ma solution depuis https://stackoverflow.com/a/40778162/2571249

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); bottomNavigationView.setOnNavigationItemSelectedListener(this); Menu menu = bottomNavigationView.getMenu(); this.onNavigationItemSelected(menu.findItem(R.id.action_favorites)); } 

Je ne veux pas modifier votre code. Si oui, je vous ai recommandé d’essayer BottomNavigationViewEx 。

Vous avez juste besoin de remplacer appelez une méthode setCurrentItem(index); et getCurrentItem()

Cliquez ici pour voir l'image

Semble être corrigé dans SupportLibrary 25.1.0 🙂 Edit: Il semble que l’état de la sélection soit enregistré lors de la rotation de l’écran.

Au-dessus de l’API 25, vous pouvez utiliser setSelectedItemId (menu_item_id) mais sous API 25 vous devez faire différemment, le menu utilisateur pour obtenir le descripteur, puis définir l’élément spécifique Checked to Checked

Il suffit d’append une autre façon d’effectuer une sélection par programmation – c’est probablement ce qui était l’intention en premier lieu ou peut-être que cela a été ajouté plus tard.

 Menu bottomNavigationMenu = myBottomNavigationMenu.getMenu(); bottomNavigationMenu.performIdentifierAction(selected_menu_item_id, 0); 

performIdentifierAction prend un identifiant d’élément de Menu et un indicateur.

Voir la documentation pour plus d’informations.

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

Le seul «moins» de la solution consiste à utiliser MenuItemImpl , qui est «interne» à la bibliothèque (bien que public).

J’ai fait un bug à Google sur le fait qu’il n’y avait pas de moyen fiable pour sélectionner la page sur un BottomNavigationView: https://code.google.com/p/android/issues/detail?id=233697

NavigationView avait apparemment un problème similaire, corrigé en ajoutant une nouvelle méthode setCheckedItem ().

Ajouter android:enabled="true" à BottomNavigationMenu Items.

Et puis définissez bottomNavigationView.setOnNavigationItemSelectedListener(mListener) et définissez-le comme sélectionné en faisant bottomNavigationView.selectedItemId = R.id.your_menu_id

La reflection est une mauvaise idée.

Dirigez-vous vers cet esprit . Il existe une méthode qui effectue la sélection mais appelle également le rappel:

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