web-dev-qa-db-fra.com

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 est modifiée pour revenir au premier élément, après la rotation de l'écran. Bien sûr, il serait également utile, si quelqu'un me le dise, de "sauvegarder" l'état actuel de BottomNavigationView dans la fonction onPause et de le restaurer dans onResume.

Merci!

64
Michael

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

2
Michael

Depuis l'API 25.3.0, la méthode setSelectedItemId(int id) a été introduite, ce qui vous permet de marquer un élément comme sélectionné comme s'il était exploité.

De docs:

Définissez l'ID d'élément de menu sélectionné. Cela se comporte comme si vous tapotiez un objet.

Exemple de code:

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

IMPORTANT

VousDEVEZavez déjà ajouté tous les éléments au menu et paramétrez l'écouteur avant d'appeler setSelectedItemId afin que BottomNavigationView puisse exécuter le comportement du code correspondant. Si vous appelez setSelectedItemId avant d'ajouter les éléments de menu et de configurer l'écouteur, rien ne se passera.

99
Ricardo

Pour cliquer par programme sur l'élément BottomNavigationBar, vous devez utiliser:

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

Cela arrange correctement tous les articles avec leurs étiquettes.

43
karenms

Pour ceux qui utilisent encore SupportLibrary <25.3.0

Je ne suis pas sûr qu'il s'agisse d'une réponse complète à cette question, mais mon problème était très similaire - je devais traiter le bouton back et amener l'utilisateur à l'onglet précédent où il se trouvait. Alors, peut-être que ma solution sera utile à 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);
    }
}

N'oubliez pas que si l'utilisateur appuie sur un autre onglet de navigation BottomNavigationView ne supprime pas l'élément 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 d'instance, je pense que vous pouvez jouer avec le même action id de la vue de navigation et trouver la solution appropriée.

33
Viacheslav

Depuis la version 25.3.0, il est maintenant possible d'appeler setSelectedItemId()\o /

5
Boy
@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

   bottomNavigationView.setOnNavigationItemSelectedListener(this);
   Menu menu = bottomNavigationView.getMenu();
   this.onNavigationItemSelected(menu.findItem(R.id.action_favorites));
}
4
askarsyzdykov

Ce sera probablement ajouté dans les prochaines mises à jour. Mais en attendant, vous pouvez utiliser la réflexion.

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

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

}

Et utilisez-le ensuite dans votre fichier de mise en page 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"/>
3
cpienovi

Ajoutez Android:enabled="true" aux éléments du menu de navigation inférieur.

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

2
Rumaan Khalander

Au-dessus de l'API 25, vous pouvez utiliser setSelectedItemId (menu_item_id) Mais sous l'API 25, vous devez procéder différemment, User Menu pour obtenir le descripteur, puis définissez Checked sur Checked item spécifique.

2
mhheydarchi

Si vous ne voulez pas modifier votre code . Si c'est le cas, je vous ai recommandé d'essayer BottomNavigationViewEx

Vous devez juste remplacer une méthode setCurrentItem(index); et getCurrentItem()

Click here to view the image

2
ittianyu

Il suffit d’ajouter un autre moyen d’effectuer une sélection par programme - c’est probablement ce qui était prévu au départ ou peut-être que cela a été ajouté plus tard.

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

La performIdentifierAction prend un Menu id et un drapeau.

Voir la documentation pour plus d'informations.

1
Darwind

Vous pouvez essayer la méthode performClick:

View view = bottomNavigationView.findViewById(R.id.YOUR_ACTION);
view.performClick();
1
ismail alaoui
bottomNavigationView.setSelectedItemId(R.id.action_item1);

action_item1 est l'ID d'élément de menu.

1
Ashwini

SI VOUS AVEZ BESOIN DE PASSER DYNAMIQUEMENT DES ARGUMENTS DE FRAGMENT FAITES CECI

Il y a beaucoup de réponses (généralement répétées ou obsolètes) ici, mais aucune d’entre elles ne répond à un besoin très courant: transmettre dynamiquement différents arguments au fragment chargé dans un onglet .

Vous ne pouvez pas passer dynamiquement différents arguments au fragment chargé en utilisant setSelectedItemId(R.id.second_tab), qui appelle finalement le static OnNavigationItemSelectedListener. Pour surmonter cette limitation, j'ai fini par le faire dans mon MainActivity qui contient les onglets:

fun loadArticleTab(articleId: String) {
    bottomNavigationView.menu.findItem(R.id.tab_article).isChecked = true // use setChecked() in Java
    supportFragmentManager
        .beginTransaction()
        .replace(R.id.main_fragment_container, ArticleFragment.newInstance(articleId))
        .commit()
}

La méthode ArticleFragment.newInstance() est implémentée comme d'habitude:

private const val ARG_ARTICLE_ID = "ARG_ARTICLE_ID"

class ArticleFragment : Fragment() {

    companion object {
        /**
         * @return An [ArticleFragment] that shows the article with the given ID.
         */
        fun newInstance(articleId: String): ArticleFragment {
            val args = Bundle()
            args.putString(ARG_ARTICLE_ID, day)
            val fragment = ArticleFragment()
            fragment.arguments = args
            return fragment
        }
    }

}
0
Albert Vila Calvo

J'ai signalé à Google qu'il n'y avait aucun moyen fiable de sélectionner la page sur BottomNavigationView: https://code.google.com/p/Android/issues/detail?id=233697

Apparemment, NavigationView avait un problème similaire, qu'ils ont résolu en ajoutant une nouvelle méthode setCheckedItem (). 

0
Johan Paul
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 utilise MenuItemImpl, qui est "interne" à la bibliothèque (bien que public).

0
Alexey