Как отключить режим сдвига BottomNavigationView?
16 ответов
Реализация BottomNavigationView
имеет условие: при наличии более 3-х предметов используйте режим смены.
В данный момент вы не можете изменить его с помощью существующего API, и единственный способ отключить режим сдвига - это использовать отражение.
Вам понадобится вспомогательный класс:
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);
}
}
}
А затем применить disableShiftMode
метод на вашем BottomNavigationView
, но помните, если вы надуваете представление меню из своего кода, вы должны выполнить его после надувания.
Пример использования:
BottomNavigationView bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottom_navigation_bar);
BottomNavigationViewHelper.disableShiftMode(bottomNavigationView);
PS.
Помните, что вам нужно выполнять этот метод каждый раз, когда вы меняете пункты меню в вашем BottomNavigationView
,
ОБНОВИТЬ
Вам также необходимо обновить конфигурационный файл proguard (например, proguard-rules.pro), приведенный выше код использует отражение и не будет работать, если proguard запутывает mShiftingMode
поле.
-keepclassmembers class android.support.design.internal.BottomNavigationMenuView {
boolean mShiftingMode;
}
Спасибо Мухаммеду Альфаифи за указание на эту проблему и предоставление фрагмента.
ОБНОВЛЕНИЕ 2
Как отметила Jolanda Verhoef, новая библиотека поддержки (28.0.1-alpha1
), а также новая библиотека компонентов материалов (1.0.0-beta01
) предлагает публичное свойство, которое можно использовать для управления режимом смещения над 3 пунктами меню.
<com.google.android.material.bottomnavigation.BottomNavigationView
...
app:labelVisibilityMode="labeled"
...
/>
В библиотеке компонентов материалов это также применимо, если есть 5 пунктов меню.
Начиная с библиотеки поддержки 28.0.0-alpha1:
<android.support.design.widget.BottomNavigationView
app:labelVisibilityMode="labeled" />
Чтобы отключить текстовую анимацию, вы также можете использовать это в вашем файле измерения.xml:
<dimen name="design_bottom_navigation_active_text_size">12sp</dimen>
Теперь вы можете использовать app:labelVisibilityMode="[labeled, unlabeled, selected, auto]"
в 28-alpha
labeled
будет держать все метки видимымиunlabeled
будут показывать только иконки.selected
будет отображаться только метка для выбранного элемента и сдвиг элементов.auto
выберет маркированные или выбранные в зависимости от количества предметов, которые у вас есть. помечены для 1-3 предметов и выбраны для 3+ предметов.
Ответ Пшемыслава на языке котлина как функция расширения
@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)
}
}
Использование (с расширениями Android Kotlin):
bottom_navigation_view.disableShiftMode()
Чтобы отключить текстовую анимацию и уменьшить размер шрифта, используйте это в вашем файле измерения.xml:
<dimen name="design_bottom_navigation_text_size">10sp</dimen>
<dimen name="design_bottom_navigation_active_text_size">10sp</dimen>
Работает для меня
bottomNavigationView.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);
или же
<android.support.design.widget.BottomNavigationView
app:labelVisibilityMode="labeled" />
ОБНОВИТЬ
в 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-alpha1 возможно:
<android.support.design.widget.BottomNavigationView
app:labelVisibilityMode="labeled" />
или вы можете установить его программно.
Примечание: если вы обновляете старую версию библиотеки поддержки, не забудьте поднять версию SDK для компиляции. Проверьте версии библиотеки поддержки здесь: Поддержка библиотеки версий
Тем не менее, вы все равно можете получить сообщение labelVisibilityMode not found при компиляции, если ваше приложение зависит от более старых версий библиотеки поддержки проектирования. Если это так, попробуйте обновить до версии с данной зависимостью, которая зависит по крайней мере от версии 28.0.0-alpha1 библиотеки поддержки проектирования. Если это невозможно, определите зависимость явно.
Если вы используете Gradle
- Вы можете проверить свои зависимости, запустив задачу зависимостей и найти номер версии com.android.support:design.
Чтобы явно добавить поддержку поддержки дизайна в ваш build.gradle:
реализация 'com.android.support:design:28.0.0'
Для обновленного ответа используем значение по умолчанию. Обновление до последней библиотеки дизайна
реализация "com.android.support:design:28.0.0"
и поместите в ваши атрибуты BottomNavigationView xml
app:itemHorizontalTranslationEnabled="false"
Вы можете поставить это также программно
bottomNavigationView.setItemHorizontalTranslationEnabled(false);
Вы можете найти источник здесь BottomNavigationView
Надеюсь, это поможет вам.
Это очень просто, просто добавьте свойство в BottomNaviationView
app:labelVisibilityMode="unlabeled"
На ваш 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>
что приводит к следующему
https://stackru.com/images/61d496da629a32c8c5e9d90d41895ce f2490969d.jpg
У меня было странное поведение с BottomNavigationView. Когда я выбирал какой-либо элемент / фрагмент в нем, фрагмент толкает BottomNavigationView чуть ниже, поэтому текст BottomNavigationView идет ниже экрана, поэтому видны только значки, а текст скрывается при нажатии любого элемента.
Если вы столкнулись с таким странным поведением, то вот решение. Просто удали
android:fitsSystemWindows="true"
в вашем корневом макете фрагмента. Просто уберите это и бум! BottomNavigationView будет работать нормально, теперь он может быть показан с текстом и значком. У меня было это в моем корне CoordinatorLayout фрагмента.
Также не забудьте добавить
BottomNavigationViewHelper.disableShiftMode(bottomNavigationView);
в вашей активности, чтобы отключить режим переключения. Хотя это не совсем связано с заданным вопросом, но все же я считаю это полезным.
Обновите вашу библиотеку поддержки до 28.0.0.
bottomNav.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);
Это сторонняя библиотека, которую я использую, и она имеет много опций настройки, таких как отключение режима сдвига, отображение только значков, настройка размера значков и т. Д. https://git hub.com/ittianyu/BottomNavigationViewEx
Чтобы полностью удалить анимацию:
Если вы также хотите избавиться от этой раздражающей маленькой анимации верхнего поля, вам нужно больше кода отражения. Вот полное решение, которое удаляет любую анимацию:
@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");
}
}
И убедитесь, что добавили это в свой конфигурационный файл proguard:
-keepclassmembers class android.support.design.internal.BottomNavigationMenuView {
boolean mShiftingMode;
}
-keepclassmembers class android.support.design.internal.BottomNavigationItemView {
int mShiftAmount;
}
Если вы используете support:design:28.0.0 добавьте эту строку app:labelVisibilityMode="unlabeled" в ваш BottomNavigationView
Я использую Android Studio 4.0.1 для его разработки. Вот мой результат...
О 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);BottomNavigationViewHelper.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();
}
}
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>
Просто хочу добавить, что выше этого метода disableShiftMode добавить ниже код тоже. @SuppressLint("RestrictedApi")
Вы можете использовать это для отображения текста и значков в BottomNevigationView от 3 до 5 элементов и остановки сдвига.
app:labelVisibilityMode="labeled"
Но вы столкнетесь с проблемой обрезки длинного текста в BottmNevigationView для 5 элементов. для этого я нашел хорошее решение для остановки смещения текста, а также иконки BottomNevigationView. Вы также можете остановить смещение текста и значков в BottomNevigationView. Фрагменты кода приведены здесь.
1. Добавьте эту строку кода в 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>
Я получил помощь по этой ссылке и ссылке. Вы также можете получить помощь, изучив эти ссылки. Это мне очень помогает. Надеюсь, это также поможет вам. Спасибо....