web-dev-qa-db-fra.com

BottomNavigationView - Comment décocher tous les MenuItems et garder les titres affichés?

Comme j'aimais le design de BottomNavigationView j'ai décidé d'implémenter un nouveau menu pour mon application avec, au lieu d'utiliser simplement de simples boutons.

J'ai pris this post comme ligne directrice.

Selon BottomNavigationViewdocumentation , son but est de

fournir une navigation rapide entre les vues de haut niveau d'une application. Il est principalement conçu pour une utilisation sur mobile.

Dans mon cas, je veux juste que chaque MenuItem lance une activité, mais par défaut il y a toujours un MenuItem sélectionné:

enter image description here

J'ai essayé de mettre la couleur au blanc avec:

app:itemIconTint="@color/white"
app:itemTextColor="@color/white"

Pourtant, MenuItem visiblement sélectionné est différent des autres (taille du titre plus grande), ce qui me dérange toujours:

enter image description here

Je suis venu avec l'idée de placer un MenuItem caché pour sélectionner comme:

<item
Android:id="@+id/uncheckedItem"
Android:title="" />

et faire sa vue GONE:

 bottomNavigationView.getMenu().findItem(R.id.uncheckedItem).setChecked(true);
 bottomNavigationView.findViewById(R.id.uncheckedItem).setVisibility(View.GONE);

Cela rend tous les MenuItems décochés, mais par défaut BottomNavigationView cache les titres, car il a plus de 3 MenuItems à afficher, même si le quatrième MenuItem est réglé sur GONE:

enter image description here

Donc, ma question demeure, est-il possible de désélectionner tous les MenuItems et de conserver ses titres affichés?

16
Victor R. Oliveira

J'ai trouvé ma propre solution en fusionnant mes progrès avec this post.

Étapes:

  1. Mise à jour de proguard-rules.pro et de la synchronisation
  2. Créer un assistant pour désactiver le mode de décalage BottomNavigationView
  3. Créer un élément à masquer sur Menu.xml
  4. Gonfler le fondNavigationView
  5. Définir l'élément à masquer comme vérifié disparu
  6. Utilisez Helper pour désactiver le mode Shifting

Sortie:

enter image description here

Code de travail:

proguard-rules.pro:

-keepclassmembers class Android.support.design.internal.BottomNavigationMenuView {
    boolean mShiftingMode;
}

BottomNavigationShiftHelper.Java:

public class BottomNavigationShiftHelper {

    private final static String TAG = "DEBUG_BOTTOM_NAV_UTIL";

    public static void disableShiftMode(BottomNavigationView view) {
        BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);
        try {
            Field shiftingMode = menuView.getClass().getDeclaredField("mShiftingMode");
            shiftingMode.setAccessible(true);
            shiftingMode.setBoolean(menuView, false);
            shiftingMode.setAccessible(false);
            for (int i = 0; i < menuView.getChildCount(); i++) {
                BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i);
                item.setShiftingMode(false);
                // set once again checked value, so view will be updated
                item.setChecked(item.getItemData().isChecked());
            }
        } catch (NoSuchFieldException e) {
            Log.d(TAG, "Unable to get shift mode field");
        } catch (IllegalAccessException e) {
            Log.d(TAG, "Unable to change value of shift mode");
        }
    }
}

Exemple d'activité.Java:

 private void loadNavigationBar() {
        BottomNavigationView bottomNavigationView = (BottomNavigationView)
                findViewById(R.id.navigation_bar);

        bottomNavigationView.getMenu().findItem(R.id.uncheckedItem).setChecked(true);
        bottomNavigationView.findViewById(R.id.uncheckedItem).setVisibility(View.GONE);

        BottomNavigationViewUtils.disableShiftMode(bottomNavigationView);

        bottomNavigationView.setOnNavigationItemSelectedListener(
                new BottomNavigationView.OnNavigationItemSelectedListener() {
                    @Override
                    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                        switch (item.getItemId()) {
                            case R.id.newList:
                                //Do The Math
                                break;
                            case R.id.loadList:
                                //Do The Math
                                break;
                            case R.id.settings:
                                //Do The Math
                                break;
                        }
                        return false;
                    }
                });
    }

BottomNavigationMenu.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto">
    <item
        Android:id="@+id/newList"
        Android:enabled="true"
        Android:icon="@drawable/new_list"
        Android:title="@string/common.button.list.new"
        app:showAsAction="withText" />
    <item
        Android:id="@+id/loadList"
        Android:enabled="true"
        Android:icon="@drawable/load"
        Android:title="@string/common.button.list.load"
        app:showAsAction="withText" />
    <item
        Android:id="@+id/settings"
        Android:enabled="true"
        Android:icon="@drawable/settings"
        Android:title="@string/common.label.settings"
        app:showAsAction="withText" />
    <item
        Android:id="@+id/uncheckedItem"
        Android:title="" />
</menu>

BottomNavigationComponent (dans Activity.xml):

<Android.support.design.widget.BottomNavigationView
    Android:id="@+id/navigation_bar"
    Android:layout_width="fill_parent"
    Android:layout_height="wrap_content"
    app:itemIconTint="@color/white"
    app:itemTextColor="@color/white"
    Android:background="@drawable/BottomNavigationMenu.xml"
    app:menu="@menu/supercart_bottom_navigation" />
3
Victor R. Oliveira
mNavigationBottom.getMenu().setGroupCheckable(0, false, true);
18
Rony Tesler

Pour désélectionner tous les éléments, j'ai créé cette extension:

fun BottomNavigationView.uncheckAllItems() {
    menu.setGroupCheckable(0, true, false)
    for (i in 0 until menu.size()) {
        menu.getItem(i).isChecked = false
    }
    menu.setGroupCheckable(0, true, true)
}

menu.setGroupCheckable (0, true, false) le rend possible. Le troisième paramètre a rendu le menu non exclusif, puis dans la boucle, vous modifiez l'état vérifié. Pour terminer, réglez à nouveau le menu sur Exclusif.

Ici le doc

9
user2003047

Merci pour votre idée. Je l'ai implémenté dans ma lib. J'ai une meilleure façon de le faire en réfléchissant. Il ne montrera donc pas d'espace.

Si vous avez de l'intérêt. Cliquez ici: https://github.com/ittianyu/BottomNavigationViewEx

private void initBottomViewAndLoadFragments(final BottomNavigationViewEx bnve) {
    bnve.enableAnimation(false);
    bnve.enableShiftingMode(false);
    bnve.enableItemShiftingMode(false);

    // use the unchecked color for first item
    bnve.setIconTintList(0, getResources().getColorStateList(R.color.bnv_unchecked_black));
    bnve.setTextTintList(0, getResources().getColorStateList(R.color.bnv_unchecked_black));

    bnve.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {

        private boolean firstClick = true;
        private int lastItemId = -1;

        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            // restore the color when click
            if (firstClick) {
                firstClick = false;
                bnve.setIconTintList(0, getResources().getColorStateList(R.color.selector_bnv));
                bnve.setTextTintList(0, getResources().getColorStateList(R.color.selector_bnv));
            }

            if (firstClick || lastItemId == -1 || lastItemId != item.getItemId()) {
                lastItemId = item.getItemId();
            } else {
                return false;
            }

            // do stuff
            return fillContent(item.getItemId());
        }
    });
}

- res/color/selector_bnv.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <item Android:color="@color/bnv_checked_white" Android:state_checked="true" />
    <item Android:color="@color/bnv_unchecked_black" />
</selector>

- res/values ​​/ colours.xml

<color name="bnv_checked_white">@Android:color/white</color>
<color name="bnv_unchecked_black">@Android:color/black</color>
5
ittianyu

Votre solution semble changer l'espace entre les articles

Voilà ma solution:

"Il suffit de définir la couleur du clic comme la couleur du non-clic."

par exemple:

private void changeMenuItemCheckedStateColor(BottomNavigationView bottomNavigationView, String checkedColorHex, String uncheckedColorHex) {
    int checkedColor = Color.parseColor(checkedColorHex);
    int uncheckedColor = Color.parseColor(uncheckedColorHex);

    int[][] states = new int[][] {
            new int[] {-Android.R.attr.state_checked}, // unchecked
            new int[] {Android.R.attr.state_checked}, // checked

    };

    int[] colors = new int[] {
            uncheckedColor,
            checkedColor
    };

    ColorStateList colorStateList = new ColorStateList(states, colors);

    bottomNavigationView.setItemTextColor(colorStateList);
    bottomNavigationView.setItemIconTintList(colorStateList);

}

si vous souhaitez décocher tous les éléments, vous pouvez

changeMenuItemCheckedStateColor(mBottomNavigationView, "#999999", "#999999");

si vous souhaitez restaurer le paramètre de couleur, vous pouvez

changeMenuItemCheckedStateColor(mBottomNavigationView, "FF743A", "999999");
2
楊舜淼

C'est la même chose que la réponse acceptée sauf que j'ai changé deux lignes de code marquées ci-dessous. Lors de la boucle à travers les BottomNavigationItemViews, j'ai défini check à false toujours et j'ai également défini checkable à false. Cela empêche les éléments de menu de changer de taille. Vous avez toujours besoin de cette règle de progression:

      -keepclassmembers class Android.support.design.internal.BottomNavigationMenuView {
         boolean mShiftingMode;
      }

Code mis à jour:

    static void removeShiftMode(BottomNavigationView view)
    {
        BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);
        try
        {
            Field shiftingMode = menuView.getClass().getDeclaredField("mShiftingMode");
            shiftingMode.setAccessible(true);
            shiftingMode.setBoolean(menuView, false);
            shiftingMode.setAccessible(false);
            for (int i = 0; i < menuView.getChildCount(); i++)
            {
                BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i);
                item.setShiftingMode(false);
                item.setChecked(false); // <--- This line changed
                item.setCheckable(false);  // <-- This line was added
            }
        }
        catch (NoSuchFieldException e)
        {
            Log.e("ERROR NO SUCH FIELD", "Unable to get shift mode field");
        }
        catch (IllegalAccessException e)
        {
            Log.e("ERROR ILLEGAL ALG", "Unable to change value of shift mode");
        }

   }
0
tim.paetz

Essayez ça, ça a marché pour moi

 <item
    Android:id="@+id/uncheckedItem"
    Android:visible="false"
    Android:title="" />

et mettre

bottomNavigationView.getMenu().findItem(R.id.uncheckedItem).setChecked(true);

enter image description here

vous obtenez tous les éléments de menu non sélectionnés; puisque la sélection est donnée pour uncheckedItem qui est invisible

J'espère que cela vous a aidé.

0
Amrutha Saj

Il y a une exception dans la réponse acceptée où nous définissons le nombre maximum d'éléments que nous ne pouvons pas implémenter ce code.

Je me suis référé d'ici TextSize personnalisé de prise en charge de BottomNavigationView Android

Dans votre dimen.xml, vous pouvez mettre:

<dimen name="design_bottom_navigation_text_size" tools:override="true">10sp</dimen>
<dimen name="design_bottom_navigation_active_text_size" tools:override="true">10sp</dimen>

Ce faisant, vous remplacez la valeur par défaut de dimen que les classes internes de BottomNavigationView utilisent. Soyez donc prudent.

Définissez ce code dans votre méthode onCreate où la vue de navigation inférieure a été initialisée

mNavigationBottom.getMenu().setGroupCheckable(0, false, true);

et enfin définissez votre barre de navigation inférieure comme ceci:

 <com.google.Android.material.bottomnavigation.BottomNavigationView
    Android:id="@+id/nav_view"
    Android:layout_width="match_parent"
    Android:layout_height="?attr/actionBarSize"
    Android:layout_gravity="bottom"
    Android:background="?android:attr/windowBackground"
    Android:fitsSystemWindows="true"
    app:labelVisibilityMode="labeled"
    app:layout_anchorGravity="fill"
    app:menu="@menu/bottom_nav_menu" />

Dans cet ensemble, votre application: labelVisibilityMode à étiquetée

0

La meilleure réponse mNavigationBottom.getMenu().setGroupCheckable(0, false, true) n'a pas fonctionné pour moi. Il montrait toujours le premier élément comme étant sélectionné.

Ce qui a fonctionné pour moi, c'est d'avoir un élément invisible et de le sélectionner, exactement comme vous l'avez fait dans la question.

Ajouter app:labelVisibilityMode="labeled" à votre BottomNavigationView pour que tous les éléments restent visibles avec leurs titres.

0
Dan Bray