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 BottomNavigationView
documentation , 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é:
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:
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
:
Donc, ma question demeure, est-il possible de désélectionner tous les MenuItems et de conserver ses titres affichés?
J'ai trouvé ma propre solution en fusionnant mes progrès avec this post.
Étapes:
Sortie:
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" />
mNavigationBottom.getMenu().setGroupCheckable(0, false, true);
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.
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>
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");
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");
}
}
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);
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é.
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
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.