如何禁用BottomNavigationView转换模式?

Nat*_*ein 139 android android-support-design bottomnavigationview

BottomNavigationView不显示不活动的菜单标题.

如何在bottomNavigationBar中显示所有菜单元素的标题?问题是在我的情况下只显示了点击元素的标题.

在此输入图像描述

小智 323

执行BottomNavigationView条件:当有超过3项时,则使用shift模式.

此时您无法通过现有API更改它,并且禁用shift模式的唯一方法是使用反射.

你需要帮助类:

import android.support.design.internal.BottomNavigationItemView;
import android.support.design.internal.BottomNavigationMenuView;
import android.support.design.widget.BottomNavigationView;
import android.util.Log;
import java.lang.reflect.Field;

public class BottomNavigationViewHelper {
    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);
                //noinspection RestrictedApi
                item.setShiftingMode(false);
                // set once again checked value, so view will be updated
                //noinspection RestrictedApi
                item.setChecked(item.getItemData().isChecked());
            }
        } catch (NoSuchFieldException e) {
            Log.e("BNVHelper", "Unable to get shift mode field", e);
        } catch (IllegalAccessException e) {
            Log.e("BNVHelper", "Unable to change value of shift mode", e);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后disableShiftMode在你的方法上应用方法BottomNavigationView,但是请记住,如果你从代码中膨胀菜单视图,你必须在膨胀后执行它.

用法示例:

BottomNavigationView bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottom_navigation_bar);
BottomNavigationViewHelper.disableShiftMode(bottomNavigationView);
Run Code Online (Sandbox Code Playgroud)

PS.

请记住,每次更改菜单项时,都需要执行此方法BottomNavigationView.

UPDATE

您还需要更新proguard配置文件(例如proguard-rules.pro),上面的代码使用反射,如果proguard对该mShiftingMode字段进行模糊处理将无法工作.

-keepclassmembers class android.support.design.internal.BottomNavigationMenuView { 
    boolean mShiftingMode; 
}
Run Code Online (Sandbox Code Playgroud)

感谢Muhammad Alfaifi指出这个问题提供片段.

更新2

正如Jolanda Verhoef指出的那样,新的Support库(28.0.0-alpha1)以及新的Material Components库(1.0.0-beta01)提供了一个公共属性,可用于操作3个菜单项的移位模式.

<com.google.android.material.bottomnavigation.BottomNavigationView
    ...
    app:labelVisibilityMode="labeled"
    ... 
/>
Run Code Online (Sandbox Code Playgroud)

在材料组件库中,如果有5个菜单项,它也适用.

  • 新的支持库(28.0.0-alpha1)支持通过app更改此行为:labelVisibilityMode ="labeled" (18认同)
  • 该字段将被混淆,因此除非您在proguard规则文件中将其排除,否则无法更改其值 (17认同)
  • ****Proguard :( (10认同)
  • -keepclassmembers类android.support.design.internal.BottomNavigationMenuView {boolean mShiftingMode; } (8认同)
  • 有时候,我真的很想知道为什么谷歌强迫它在开发人员上实现视图.虽然Google+应用程序本身有4个选项,但如果可以的话,这个简单的功能应该可以通过一个简单的功能访问!类似的问题与TabLayout有关,后来在支持库中修复了很多.感谢Original Replier和@MuhammadAlfaifi的改进措施. (8认同)
  • 除了Jolanda Verhoef,当你使用5个图标时,再次发生移位.但现在有一个名为setItemHorizo​​ntalTranslationEnabled的方法.将此设置为false会将图标保留在原位. (3认同)
  • 它完美地运作!! 我希望`BottomNavigationView`可以选择切换它而不需要反射 (2认同)

小智 46

自支持库28.0.0-alpha1:

<android.support.design.widget.BottomNavigationView
    app:labelVisibilityMode="labeled" />
Run Code Online (Sandbox Code Playgroud)


Paf*_*oid 28

要禁用文本动画,您还可以在dimens.xml文件中使用它:

<dimen name="design_bottom_navigation_active_text_size">12sp</dimen>
Run Code Online (Sandbox Code Playgroud)

  • @RohanKandwal需要添加`tools:override ="true"` (10认同)

Aid*_*ing 18

你现在可以使用app:labelVisibilityMode="[labeled, unlabeled, selected, auto]"28-alpha

  • labeled 将保持所有标签可见.
  • unlabeled 将只显示图标.
  • selected 将仅显示所选项目的标签和班次项目.
  • auto将根据您拥有的物品数量选择标记或选择.标记为1-3项,并选择3项以上.


Ele*_*gyD 17

Przemysław在Kotlin中作为扩展函数的答案

@SuppressLint("RestrictedApi")
fun BottomNavigationView.disableShiftMode() {
    val menuView = getChildAt(0) as BottomNavigationMenuView
    try {
        val shiftingMode = menuView::class.java.getDeclaredField("mShiftingMode")
        shiftingMode.isAccessible = true
        shiftingMode.setBoolean(menuView, false)
        shiftingMode.isAccessible = false
        for (i in 0 until menuView.childCount) {
            val item = menuView.getChildAt(i) as BottomNavigationItemView
            item.setShiftingMode(false)
            // set once again checked value, so view will be updated
            item.setChecked(item.itemData.isChecked)
        }
    } catch (e: NoSuchFieldException) {
        Log.e(TAG, "Unable to get shift mode field", e)
    } catch (e: IllegalStateException) {
        Log.e(TAG, "Unable to change value of shift mode", e)
    }
}
Run Code Online (Sandbox Code Playgroud)

用法(使用Kotlin Android Extensions):

bottom_navigation_view.disableShiftMode()
Run Code Online (Sandbox Code Playgroud)


UgA*_*0FF 10

适合我

bottomNavigationView.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);
Run Code Online (Sandbox Code Playgroud)

要么

<android.support.design.widget.BottomNavigationView
    app:labelVisibilityMode="labeled" />
Run Code Online (Sandbox Code Playgroud)


Abh*_*hek 9

要禁用文本动画并减小字体大小,请在dimens.xml文件中使用:

<dimen name="design_bottom_navigation_text_size">10sp</dimen> 
<dimen name="design_bottom_navigation_active_text_size">10sp</dimen>
Run Code Online (Sandbox Code Playgroud)


Nar*_*yan 6

UPDATE

in Android sdk version 28 and above they have changed item.setShiftingMode(false) to item.setShifting(false)

Also they removed the field mShiftingMode

So usage will be

 BottomNavigationHelper.removeShiftMode(bottomNav);
 bottomNav.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);


 private static final class BottomNavigationHelper {
    @SuppressLint("RestrictedApi")
    static void removeShiftMode(BottomNavigationView view) {
        BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);
        for (int i = 0; i < menuView.getChildCount(); i++) {
            BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i);
            //noinspection RestrictedApi
            item.setShifting(false);
            item.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);

            // set once again checked value, so view will be updated
            //noinspection RestrictedApi
            item.setChecked(item.getItemData().isChecked());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

正如其他人所指出的那样,从支持库28.0.0-alpha1开始,它是可能的:

<android.support.design.widget.BottomNavigationView
app:labelVisibilityMode="labeled" />
Run Code Online (Sandbox Code Playgroud)

或者你可以以编程方式设置它.

注意:如果要从旧版本的支持库升级,请不要忘记提高编译SDK版本.在此处检查支持libraray的版本:支持库版本

但是,如果您的应用程序依赖于旧版本的设计支持库,则编译时仍可能会看到labelVisibilityMode not found消息.如果是这种情况,请尝试升级到给定依赖项的版本,该版本至少取决于设计支持库的28.0.0-alpha1版本.如果不可能,请明确定义依赖项.

如果您使用Gradle

  1. 您可以通过运行依赖项任务来检查您的depdendecies 并搜索com.android.support:design的版本号.
  2. 要在build.gradle中显式添加设计支持依赖:

    实现'com.android.support:design:28.0.0'


Les*_* L. 5

对于使用默认值的更新答案。更新到最新的设计库

实现“com.android.support:design:28.0.0”

并放入您的 BottomNavigationView xml 属性

app:itemHorizontalTranslationEnabled="false"
Run Code Online (Sandbox Code Playgroud)

您也可以以编程方式放置它

bottomNavigationView.setItemHorizontalTranslationEnabled(false);
Run Code Online (Sandbox Code Playgroud)

你可以在这里找到源BottomNavigationView

希望这对你有帮助。