How to disable BottomNavigationView shift mode?

BottomNavigationView doesn't show menu's title that are inactive.

How to show titles of all menu elements in bottomNavigationBar? The problem is that in my case shown only title of element that is clicked.

enter image description here

85116 次浏览

实现 BottomNavigationView有条件: 当有3个以上的项目时,然后使用移位模式。

此时,您不能通过现有的 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);
}
}
}

然后在 BottomNavigationView上应用 disableShiftMode方法,但是请记住,如果要从代码中充气菜单视图,则必须在充气后执行它。

示例用法:

BottomNavigationView bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottom_navigation_bar);
BottomNavigationViewHelper.disableShiftMode(bottomNavigationView);

附言。

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

更新

您还需要更新前卫配置文件(例如,前卫规则)。Pro) ,上面的代码使用反射,如果前卫混淆了 mShiftingMode字段就不会工作。

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

感谢穆罕默德阿尔法菲指出 这个问题提供片段

更新2

Jolanda Verhoef 指出,新的支持库(28.0.0-alpha1)和新的 材料组件库(1.0.0-beta01)提供了一个公共属性,可以用来操纵3个菜单项的移动模式。

<com.google.android.material.bottomnavigation.BottomNavigationView
...
app:labelVisibilityMode="labeled"
...
/>

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

更新3

正如@ThomasSunderland 也指出的那样,您可以将此属性设置为 false app:itemHorizontalTranslation="false",而不使用 Enabled后缀来禁用移位动画。

您可以查看底部导航 给你样式的完整指南

为了禁用文本动画,您还可以将其用于量纲.xml 文件:

<dimen name="design_bottom_navigation_active_text_size">12sp</dimen>

您可能还需要在清单中添加以下内容:

tools:override="true"

要禁用文本动画并减小字体大小,可以使用以下方法来实现:

<dimen name="design_bottom_navigation_text_size">10sp</dimen>
<dimen name="design_bottom_navigation_active_text_size">10sp</dimen>

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

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

android:fitsSystemWindows="true"

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

也别忘了加上

BottomNavigationViewHelper.disableShiftMode(bottomNavigationView);

在你的活动中关闭移动模式。 虽然这和问题没有什么关系,但是我还是觉得这很有帮助。

这是我使用的第三方库,它有很多定制选项,比如禁用移位模式,只显示图标,设置图标大小等等。 下方导航视图

作为一个扩展函数的 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)
}
}

用法(使用 Kotlin Android 扩展程序) :

bottom_navigation_view.disableShiftMode()

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

  • labeled 将保持所有标签可见。
  • unlabeled 将只显示图标。
  • selected 将只显示所选项目和 shift 项目的标签。
  • auto 将根据您拥有的项目数量选择标记或选择。标记为1-3个项目,选择为3 + 项目。

只是想添加上面这个方法 disableShiftMode 添加下面的代码太。 @ SuppressLint (“受限制的 Api”)

完全移除动画:

如果你还想摆脱那个烦人的小顶部边缘动画,你需要更多的反射代码。下面是消除任何动画的完整解决方案:

@SuppressLint("RestrictedApi")
private 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);


Field shiftAmount = item.getClass().getDeclaredField("mShiftAmount");
shiftAmount.setAccessible(true);
shiftAmount.setInt(item, 0);
shiftAmount.setAccessible(false);


item.setChecked(item.getItemData().isChecked());
}
} catch (NoSuchFieldException e) {
Timber.e(e, "Unable to get fields");
} catch (IllegalAccessException e) {
Timber.e(e, "Unable to change values");
}
}

并确保将其添加到您的前卫配置文件:

-keepclassmembers class android.support.design.internal.BottomNavigationMenuView {
boolean mShiftingMode;
}
-keepclassmembers class android.support.design.internal.BottomNavigationItemView {
int mShiftAmount;
}

自支持库 28.0.0-字母1:

<android.support.design.widget.BottomNavigationView
app:labelVisibilityMode="labeled" />

我没问题

bottomNavigationView.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);

或者

<android.support.design.widget.BottomNavigationView
app:labelVisibilityMode="labeled" />

正如其他人指出的那样,自 支援库28.0.0-alpha1以来,这是可能的:

<android.support.design.widget.BottomNavigationView
app:labelVisibilityMode="labeled" />

或者你可以把它设为 以程序化的方式

注意: 如果您正在从旧版本的支持库升级,不要忘记引发编译 SDK 版本。 在这里检查支持库的版本: 支持库版本

但是,如果您的应用程序依赖于设计支持库的旧版本,那么在编译时您仍然可能会收到 找不到 labelVisibilityMode消息。如果是这种情况,尝试升级到给定依赖项的一个版本,这至少取决于28.0.0-alpha1版本的设计支持库。如果不可能,那么显式地定义依赖项。

如果你用格拉德尔

  1. 你可以通过 运行 依赖关系任务并搜索 支持: design的版本号。
  2. 要在 建造,分级中明确添加设计支持依赖项:

    实现‘ com.android.support: design: 28.0.0’

使用默认值更新应答。更新到最新的设计库

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

并将其放到 BottomNavigationView xml 属性中

app:itemHorizontalTranslationEnabled="false"

你也可以用编程的方式

bottomNavigationView.setItemHorizontalTranslationEnabled(false);

你可以在这里找到来源 底部导航视图

希望这个能帮到你。

更新

在 Android sdk 28及以上版本中,他们将 item.setShiftingMode(false)改为 item.setShifting(false)

他们还删除了字段 mShiftingMode

因此,使用将是

 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());
}
}
}

将支持库更新为28.0.0。

bottomNav.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);

如果您正在使用 support: design: 28.0.0,请将这一行应用程序: labelVisibilityMode = “ unlabel”添加到 BottomNavigationView

在你的 BottomNavigationView中加入 app:labelVisibilityMode="unlabeled"

<android.support.design.widget.BottomNavigationView
app:menu="@menu/bn_menu"
android:layout_height="56dp"
android:layout_width="match_parent"
app:labelVisibilityMode="unlabeled">


</android.support.design.widget.BottomNavigationView>

结果如下

Android Bottom Navigation View Disable Text and Shift

你可以使用它来显示3到5个项目的 BottomNevigationView 上的文本和图标,并停止移动。

 app:labelVisibilityMode="labeled"

但是在 BottmNevigationView 上有5个项目会遇到长文本切割的问题。为此,我找到了一个很好的解决方案,停止移动的文本以及图标的 BottomNevigationView。你也可以在 BottomNevigationView 上停止文本和图标的移动。这里给出了代码的摘要。

在 BottomNevigationView 中添加一行代码,如下所示

<android.support.design.widget.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="@dimen/seventy_dp"
android:layout_semitransparent="true"
android:background="@color/colorBottomNev"
android:showAsAction="always|withText"
app:itemIconTint="@drawable/bottom_navigation_colors"
app:itemTextColor="@drawable/bottom_navigation_colors"
app:itemTextAppearanceActive="@style/BottomNavigationViewTextStyle"
app:itemTextAppearanceInactive="@style/BottomNavigationViewTextStyle"
app:menu="@menu/bottom_navigation_menu"
app:labelVisibilityMode="labeled"/>

2. 添加如下菜单项:-

 <?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/action_catalogue"
android:icon="@drawable/catalogue"
android:title="@string/catalogue"
android:enabled="true"
app:showAsAction="ifRoom" />


<item
android:id="@+id/action_contracts"
android:icon="@drawable/contract"
android:title="@string/contracts"
android:enabled="true"
app:showAsAction="ifRoom" />


<item
android:id="@+id/action_prospects"
android:icon="@drawable/prospect"
android:title="@string/prospects"
android:enabled="true"
app:showAsAction="ifRoom" />


<item
android:id="@+id/action_performance"
android:icon="@drawable/performance"
android:title="@string/performance"
android:enabled="true"
app:showAsAction="ifRoom" />


<item
android:id="@+id/action_advance"
android:icon="@drawable/advance"
android:title="@string/advance"
android:enabled="true"
app:showAsAction="ifRoom" />


</menu>

3. 在 style.xml 文件中添加这种样式:

 <style name="BottomNavigationViewTextStyle">
<item name="android:fontFamily">@font/montmedium</item>
<item name="android:textSize">10sp</item>
<item name="android:duplicateParentState">true</item>
<item name="android:ellipsize">end</item>
<item name="android:maxLines">1</item>
</style>

4)将这些文件添加到 Dimen 文件夹中

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<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>
</resources>

我得到了这些 链接链接的帮助。您还可以通过研究这些链接获得帮助。这对我很有帮助。希望这个也能帮到你。谢谢。

很简单,只需在 BottomNaviationView 中添加一个属性

app:labelVisibilityMode="unlabeled"

Https://android.jlelse.eu/disable-shift-label-animation-from-bottom-navigation-android-b42a25dcbffc

1

<com.google.android.material.bottomnavigation.BottomNavigationView
...
app:itemHorizontalTranslationEnabled="false"/>

2

<com.google.android.material.bottomnavigation.BottomNavigationView
...
app:labelVisibilityMode="labeled"/>

3

<resources xmlns:tools="http://schemas.android.com/tools">
<dimen name="design_bottom_navigation_active_text_size"
tools:override="true">12sp</dimen>

我使用 Android Studio 4.0.1来开发它。 以下是我的结果..。 enter image description here

关于 BottomNavigationViewHelper.java 我的代码就是工作

import com.google.android.material.bottomnavigation.BottomNavigationItemView;
import com.google.android.material.bottomnavigation.BottomNavigationMenuView;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.bottomnavigation.LabelVisibilityMode;
import android.annotation.SuppressLint;
import android.util.Log;
import java.lang.reflect.Field;
public class BottomNavigationViewHelper {
@SuppressLint("RestrictedApi")
public static void disableShiftMode(BottomNavigationView view) {
view.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);
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.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());
}
} 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);
}
}
}

然后我们可以开始使用 BottomNavigationViewHelper 类 这是我的 MainActivity.java 代码。

BottomNavigationView navView = findViewById (R.id.nav _ view) ; DisableShiftMode (navView) ;

import android.os.Bundle;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomNavigationView navView = findViewById(R.id.nav_view);
BottomNavigationViewHelper.disableShiftMode(navView);
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_settings,
R.id.navigation_connection,
R.id.navigation_status,
R.id.navigation_report,
R.id.navigation_profile
).build();


NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(navView, navController);
getSupportActionBar().hide();
}
}