BottomNavigationView 始终显示图标和文本标签

我使用的是来自设计支持库版本25的 android.Support.design. widget. BottomNavigationView

compile 'com.android.support:design:25.0.0'


<android.support.design.widget.BottomNavigationView
android:id="@+id/bottomBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_gravity="center"
app:itemBackground="@color/colorPrimary"
app:menu="@menu/bottom_navigation_main"
android:forceHasOverlappingRendering="true"/>

当@menu/bottom _ 導 _ main 中只有三个操作时,它会始终显示图标和文本标签。

当有三个以上的操作时,如何同时显示图标和文本标签。

98723 次浏览

在 BottomNavigationView 类中有一个 BottomNavigationMenuView 字段,在 BottomNavigationMenuView 中有一个 BottomNavigationItemView []字段,它是底部栏中的项。

假设 n 是项的数量,BottomNavigationMenuView 将对 BottomNavigationItemView.setShiftingMode (n > 3)的每个成员调用 BottomNavigationItemView []数组。此函数决定行为(始终或仅在选择时显示标题)。

所以总是显示标题的方法是尝试调用这个方法,您可以使用反射来访问私有字段。

    BottomNavigationView bottomNavigationView= (BottomNavigationView) findViewById(R.id.bottom_navigation);




//  get the private BottomNavigationMenuView field
Field f = null;
try {
f = bottomNavigationView.getClass().getDeclaredField("mMenuView");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
f.setAccessible(true);
BottomNavigationMenuView menuView=null;
try {
menuView = (BottomNavigationMenuView) f.get(bottomNavigationView);
} catch (IllegalAccessException e) {
e.printStackTrace();
}


//  get the private BottomNavigationItemView[]  field
try {
f=menuView.getClass().getDeclaredField("mButtons");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
f.setAccessible(true);
BottomNavigationItemView[] mButtons=null;
try {
mButtons = (BottomNavigationItemView[]) f.get(menuView);
} catch (IllegalAccessException e) {
e.printStackTrace();
}




for(int i=0;i<mButtons.length;i++){
mButtons[i].setShiftingMode(false);
mButtons[i].setChecked(true);
}

在25版本中是困难的。

试试这个代码。但我认为这不是一个好的解决方案。

BottomNavigationView navigationView = (BottomNavigationView) findViewById(R.id.bottomBar);
BottomNavigationMenuView menuView = (BottomNavigationMenuView) navigationView.getChildAt(0);
for (int i = 0; i < menuView.getChildCount(); i++) {
BottomNavigationItemView itemView = (BottomNavigationItemView) menuView.getChildAt(i);
itemView.setShiftingMode(false);
itemView.setChecked(false);
}

你想要这种效果吗?

Click here to view the image

如果是这样,我建议您尝试 下方导航视图

下方导航视图的替代品: 底部栏

更新日期: 2018年5月8日

你可以用 app:labelVisibilityMode="labeled" 直接进入 <android.support.design.widget.BottomNavigationView />

资料来源: https://developer.android.com/reference/com/google/android/material/bottomnavigation/LabelVisibilityMode

不需要这下面冗长的解决方案。

上一个答案

我在 BottomNavigationView 上有些奇怪的行为。当我选择其中的任何项目/片段时,片段会把 BottomNavigationView 推得更低一些,所以 BottomNavigationView 的文本会在屏幕下方,所以只有图标可见,点击任何项目时文本会隐藏起来。

如果你正面临这种奇怪的行为,那么这里有一个解决方案。 拿开

android:fitsSystemWindows="true"

在你的片段根布局。把这个拿开,砰!BottomNavigationView 将工作良好,现在它可以显示文本和图标。 我把这个放在我的根协调器碎片布局里。

也别忘了加上

BottomNavigationViewHelper.removeShiftMode(bottomNavigationView);

在你的活动中关闭移动模式。

这就是那门课:

public class BottomNavigationViewHelper {


@SuppressLint("RestrictedApi")
public static void removeShiftMode(BottomNavigationView view) {
//this will remove shift mode for bottom navigation 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.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");
}
}
}

要一直显示标题,请尝试下面的 Kotlin 代码:

@SuppressLint("RestrictedApi")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_ofree)


navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)


val menuView = navigation.getChildAt(0) as BottomNavigationMenuView
for (i in 0 until menuView.childCount) {
val itemView = menuView.getChildAt(i) as BottomNavigationItemView
itemView.setShiftingMode(false)
itemView.setChecked(false)
}
}

下面是一个 Kotlin 扩展函数,它结合了@STAR _ ZERO 和@KishanSolanki124的解决方案。

fun BottomNavigationView.disableShiftMode() {
val menuView = getChildAt(0) as BottomNavigationMenuView


menuView.javaClass.getDeclaredField("mShiftingMode").apply {
isAccessible = true
setBoolean(menuView, false)
isAccessible = false
}


@SuppressLint("RestrictedApi")
for (i in 0 until menuView.childCount) {
(menuView.getChildAt(i) as BottomNavigationItemView).apply {
setShiftingMode(false)
setChecked(false)
}
}
}

使用方法:

myBottomNavigation.disableShiftMode()

对于那些仍在寻找解决方案并且不想依赖第三方库或运行时反射的人来说,Support Library 28/Jetpack 中的 BottomNavigationView 本身就支持始终使用文本标签。

这个 就是您正在寻找的方法。

或者在 XML 中使用 app:labelVisibilityMode="labeled"

您可以使用它在 BottomNevigationView 上显示文本和图标

app:labelVisibilityMode="labeled"

如果你使用这个,你将能够查看图标和文本

<android.support.design.widget.BottomNavigationView
app:labelVisibilityMode="labeled"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/bottom_navigation_view"
android:layout_alignParentBottom="true"
app:menu="@menu/bottom_navigation_menu"/>

您可以直接在

<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="50dp"
app:labelVisibilityMode="labeled"
android:elevation="8dp"
android:layout_alignParentBottom="true"
app:itemBackground="@drawable/bottom_navi"
app:itemTextColor="@color/white"
app:itemIconTint="@color/white"
app:menu="@menu/bottom_nav_menu_managment" />