Reputation: 1893
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.
Upvotes: 152
Views: 87724
Reputation: 3975
I use Android Studio 4.0.1 to develop it.
The following is my result...
About BottomNavigationViewHelper.java My code is work here
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);
}
}
}
Then we can start to use BottomNavigationViewHelper class And this is my code for 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();
}
}
Upvotes: 1
Reputation: 6251
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>
Upvotes: 0
Reputation: 727
It's very simple, Just add a property in BottomNaviationView
app:labelVisibilityMode="unlabeled"
Upvotes: 3
Reputation: 445
To disable the text animation you can also use this in your dimens.xml file:
<dimen name="design_bottom_navigation_active_text_size">12sp</dimen>
You might also need to add this in your manifest :
tools:override="true"
Upvotes: 31
Reputation: 4887
Implementation of BottomNavigationView
has condition: when there is more than 3 items then use shift mode.
At this moment you cannot change it through existing API and the only way to disable shift mode is to use reflection.
You'll need helper class:
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);
}
}
}
And then apply disableShiftMode
method on your BottomNavigationView
, but remember if you are inflating menu view from your code, you have to execute it after inflating.
Example usage:
BottomNavigationView bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottom_navigation_bar);
BottomNavigationViewHelper.disableShiftMode(bottomNavigationView);
PS.
Remember, you'll need to execute this method each time you change menu items in your BottomNavigationView
.
UPDATE
You also need to update proguard configuration file (e.g. proguard-rules.pro), code above uses reflection and won't work if proguard obfuscate the mShiftingMode
field.
-keepclassmembers class android.support.design.internal.BottomNavigationMenuView {
boolean mShiftingMode;
}
Thanks Muhammad Alfaifi for pointing this issue and providing snippet.
UPDATE 2
As Jolanda Verhoef pointed out the new Support library (28.0.0-alpha1
) and also the new Material Components library (1.0.0-beta01
) offers a public property which can be used to manipulate the shifting mode over 3 menu items.
<com.google.android.material.bottomnavigation.BottomNavigationView
...
app:labelVisibilityMode="labeled"
...
/>
In Material Components library it also applies if there are 5 menu items.
UPDATE 3
As @ThomasSunderland also pointed out, you can set this property to false app:itemHorizontalTranslation="false"
without Enabled
postfix to disable shifting animation.
you can check the full guide to styling the BottomNavigation here
Upvotes: 336
Reputation: 6732
You can use this for showing both text and icons on BottomNevigationView for 3 to 5 items and stop shifting.
app:labelVisibilityMode="labeled"
But you will will face a problem of long text cutting on BottmNevigationView for 5 items. for that ,I found a good solutions for stop shifting of text as well as icons of BottomNevigationView. You can also stop shifting of text as well as Icons on BottomNevigationView also. Snipshots of code is given here.
1. Add this some line of code in BottomNevigationView as shown
<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. Add Menu Items like as follows:-
<?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.Add this style in style.xml file:
<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)Add these in Dimen folder
<?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>
I got help from these link and link .You can also get get help by studying these links.This helps me a lot.Hope this also help you. Thanks....
Upvotes: -1
Reputation: 26462
To your BottomNavigationView
add 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>
which results in the following
Upvotes: 3
Reputation: 747
If you are using support:design:28.0.0 add this line app:labelVisibilityMode="unlabeled" to your BottomNavigationView
Upvotes: 1
Reputation: 825
Works for me
bottomNavigationView.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);
or
<android.support.design.widget.BottomNavigationView
app:labelVisibilityMode="labeled" />
Upvotes: 11
Reputation: 290
update your support library to 28.0.0.
bottomNav.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED);
Upvotes: 2
Reputation: 1929
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());
}
}
}
Upvotes: 6
Reputation: 1300
You can now use app:labelVisibilityMode="[labeled, unlabeled, selected, auto]"
in 28-alpha
labeled
will keep all labels visible.unlabeled
will show only icons.selected
will only show the label for the selected item and shift items.auto
will choose labeled or selected based on the number of items you have. labeled for 1-3 items and selected for 3+ items.Upvotes: 24
Reputation: 969
For updated answer using the default. Update to latest design library
implementation "com.android.support:design:28.0.0"
and put to your BottomNavigationView xml attributes
app:itemHorizontalTranslationEnabled="false"
you can put it also as programmatically
bottomNavigationView.setItemHorizontalTranslationEnabled(false);
You can find source here BottomNavigationView
Hope this helps you.
Upvotes: 5
Reputation: 71
As others have pointed out, since support library 28.0.0-alpha1 it is possible:
<android.support.design.widget.BottomNavigationView
app:labelVisibilityMode="labeled" />
or you can set it programatically.
Note: if you are upgrading from an older version of support library, do not forget to raise compile SDK version. Check versions of support libraray here: Support Library versions
However, you may still get labelVisibilityMode not found message when compile, if your app depends on older versions of the design support library. If this is the case, try to upgrade to a version of the given dependency, that depends on at least the version of 28.0.0-alpha1 of design support library. If that's not possible, define the dependency explicitly.
If you use Gradle
To add design support dependency explicitly in your build.gradle:
implementation 'com.android.support:design:28.0.0'
Upvotes: 5
Reputation: 661
Since support library 28.0.0-alpha1:
<android.support.design.widget.BottomNavigationView
app:labelVisibilityMode="labeled" />
Upvotes: 56
Reputation: 8902
If you also want to get rid of that annoying little top margin animation, you need more reflection code. Here's the complete solution that removes any animation:
@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");
}
}
And make sure to add that to your proguard configuration file:
-keepclassmembers class android.support.design.internal.BottomNavigationMenuView {
boolean mShiftingMode;
}
-keepclassmembers class android.support.design.internal.BottomNavigationItemView {
int mShiftAmount;
}
Upvotes: 2
Reputation: 187
just want to add that above this method disableShiftMode add below code too. @SuppressLint("RestrictedApi")
Upvotes: 0
Reputation: 4785
Przemysław's answer in Kotlin as an extension function
@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)
}
}
Usage (with Kotlin Android Extensions):
bottom_navigation_view.disableShiftMode()
Upvotes: 17
Reputation: 11643
This is a third party library I use and it has many customization options like disabling shift mode, showing only icons, setting icons size, etc. BottomNavigationViewEx
Upvotes: 2
Reputation: 14636
I had some weird behavior with BottomNavigationView. When I was selecting any item/fragment in it, the fragment pushes BottomNavigationView a bit lower, so text of BottomNavigationView goes below the screen, so only icons were visible and text goes hidden on clicking of any item.
If you are facing that weird behavior then Here is the solution. Just remove
android:fitsSystemWindows="true"
in your root layout of fragment. Just remove this and boom! BottomNavigationView will work fine, now it can be shown with text and icon. I had this in my root CoordinatorLayout of fragment.
Also don't forget to add
BottomNavigationViewHelper.disableShiftMode(bottomNavigationView);
in your activity to disable shifting mode. Though it is not exactly related to the asked question, but still I find this helpful.
Upvotes: 2
Reputation: 1028
To disable the text animation and decrease font size use this in your dimens.xml file:
<dimen name="design_bottom_navigation_text_size">10sp</dimen>
<dimen name="design_bottom_navigation_active_text_size">10sp</dimen>
Upvotes: 12