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!
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.
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.
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.
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.
Depuis la version 25.3.0, il est maintenant possible d'appeler setSelectedItemId()
\o /
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bottomNavigationView.setOnNavigationItemSelectedListener(this);
Menu menu = bottomNavigationView.getMenu();
this.onNavigationItemSelected(menu.findItem(R.id.action_favorites));
}
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"/>
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
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.
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()
。
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.
Vous pouvez essayer la méthode performClick:
View view = bottomNavigationView.findViewById(R.id.YOUR_ACTION);
view.performClick();
bottomNavigationView.setSelectedItemId(R.id.action_item1);
où action_item1
est l'ID d'élément de menu.
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
}
}
}
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 ().
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).