197

I am using android.support.design.widget.BottomNavigationView from design support library version 25

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"/>

When there are only three actions in @menu/bottom_navigation_main, it displays both icons and text labels at all times.

What is the way to display both icons and text labels at all the time when there are more than three actions.

Nikola Despotoski
  • 49,966
  • 15
  • 119
  • 148
Ammad Ali
  • 2,196
  • 3
  • 14
  • 18

11 Answers11

494

For anyone still looking for a solution and doesn't want to rely on third party libraries or runtime reflection, BottomNavigationView in Support Library 28/Jetpack natively supports always having text label.

This is the method you're looking for.

Or in XML, app:labelVisibilityMode="labeled"

shaishgandhi
  • 5,538
  • 1
  • 17
  • 7
90

UPDATE FROM May 8, 2018

You can use app:labelVisibilityMode="labeled" directly in <android.support.design.widget.BottomNavigationView />

Source: https://developer.android.com/reference/com/google/android/material/bottomnavigation/LabelVisibilityMode

Don't need this below lengthy solution.

PREVIOUS ANSWER

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.removeShiftMode(bottomNavigationView);

in your activity to disable shifting mode.

Here is that class:

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");
        }
    }
}
Kishan Solanki
  • 13,761
  • 4
  • 85
  • 82
  • This in combination with STAR_ZERO's answer solved my issue! – Christopher Smit Feb 19 '18 at 11:47
  • In the call you have `disableShiftMode`, and in the class `removeShiftMode`. Apart from that little discrepancy your answer solved the issue for me. I now have five menuitems without shifting and with text+icon. Thank you **very** much! – Yamakuzure Apr 03 '18 at 07:49
  • Perfect. When you have more than 3 items in your bottom navigation than, there appears a shifting mode. Using this, you can disable that shifting and hence all the icons with text appears at once. – Kishor Bikram Oli Apr 25 '18 at 10:01
19

It is difficult in version 25.

Try this code. But I think it's not good solution.

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);
}
STAR_ZERO
  • 1,400
  • 11
  • 21
16

You can use this for showing both text and icons on BottomNevigationView

app:labelVisibilityMode="labeled"

If you are using this you will be able to view both icon and text

<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"/>
Kumar Ajay
  • 222
  • 4
  • 10
11

Are you want to this effect ?

Click here to view the image

If so, I recommended you to try BottomNavigationViewEx

ittianyu
  • 509
  • 4
  • 7
  • 1
    Your library is good and impressive work But i was looking to achieve this functionality using design library 25.0.0 Unfortunately it is against the android design practice – Ammad Ali Nov 13 '16 at 08:31
  • This is not against Material Design specs, according to the "Fixed bottom navigation bar" in [the docs](https://material.io/guidelines/components/bottom-navigation.html). Also, my personal thanks for sharing this awesome library. – Serhii Jun 26 '17 at 08:23
  • 1
    This IS against the Material Design specs. If you read the document that you provided, you will see that it explicit says "If there are four or five actions, display inactive views as icons only". – Felipe Jul 30 '17 at 22:33
11

Here's a Kotlin extension function that combines @STAR_ZERO and @KishanSolanki124's solution.

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

To use it:

myBottomNavigation.disableShiftMode()
chetbox
  • 1,732
  • 19
  • 19
11

You can use app:labelVisibilityMode="labeled" directly in

<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" />
kishan verma
  • 984
  • 15
  • 17
5

in BottomNavigationView class there is a BottomNavigationMenuView field and in BottomNavigationMenuView there is a BottomNavigationItemView[] field, which is the items in the bottom bar.

Say n is the number of items, BottomNavigationMenuView will call BottomNavigationItemView.setShiftingMode(n>3) on each member of the BottomNavigationItemView[] array. This function decides the behaviour (show title always or only upon selection).

so the way to always show the titles is to try to call this method and you can use reflection to access the private fields.

    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);
        }
wei wang
  • 411
  • 5
  • 10
  • This is very good, just we need to make sure the BottomNavigationMenuView also does not shift. -> f = menuView.getClass().getDeclaredField("mShiftingMode"); f.setAccessible(true); f.setBoolean(menuView, false); – stephane k. Jan 22 '17 at 14:15
4

To show the titles all the way. Try this Kotlin code:

@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)
    }
}
Harry Zhang
  • 799
  • 9
  • 6
2

Alternative to BottomNavigationViewEx: BottomBar

Mateusz Budzisz
  • 598
  • 7
  • 15
0

The programmatically way to always show the labels

navigationView.labelVisibilityMode = NavigationBarView.LABEL_VISIBILITY_LABELED
Linh
  • 57,942
  • 23
  • 262
  • 279