BottomNavigationView with more than 3 Items: tab title is hiding
Asked Answered
A

11

94

I have implemented BottomNavigationView with Android Support Design Library 25. But when I switched the tabs, the title of other tabs are hiding. But there is no such issue in the actual Bottom Navigation View.

MyBottomNavigation

Any idea about the cause of the issue? What am I missing?

ActualBottomNavigation

Here is my code:

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.yunus.ototakip.MainActivity">

<FrameLayout
    android:id="@+id/main_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_above="@+id/bottom_navigation"
    android:layout_alignParentTop="true">
</FrameLayout>

<android.support.design.widget.BottomNavigationView
    android:id="@+id/bottom_navigation"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    app:itemBackground="@color/colorPrimary"
    app:itemIconTint="@color/beyaz"
    app:itemTextColor="@color/beyaz"
    app:menu="@menu/bottombar_menu" />

bottom_bar_menu.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
 <item
android:id="@+id/bb_menu_arac"
android:enabled="true"
android:icon="@drawable/icon_car"
android:title="@string/araclarim"
app:showAsAction="ifRoom" />
 <item
android:id="@+id/bb_menu_yakin"
android:enabled="true"
android:icon="@drawable/icon_yer"
android:title="@string/yakinimdakiler"
app:showAsAction="ifRoom" />
  <item
android:id="@+id/bb_menu_yaklasan"
android:enabled="true"
android:icon="@drawable/icon_takvim"
android:title="@string/yaklasanlar"
app:showAsAction="ifRoom" />

<item
    android:id="@+id/bb_menu_ipucu"
    android:enabled="true"
    android:icon="@drawable/icon_ipucu"
    android:title="@string/ipuclari"
    app:showAsAction="ifRoom" />
 </menu>
Alpenhorn answered 18/1, 2017 at 11:47 Comment(7)
did you tried app:showAsAction="always instead of ifRoomLabrecque
I tried, but it's still hidingAlpenhorn
check here #36032677Labrecque
@YassineBELDI is right. Check this thread (to be more concrete this answer). At the bottom is the way to disable shift mode, however I don't recommend that as it is incompliant with Material Design Guidelines. More about shift mode hereMyriagram
@YunusHaznedar if item is more than 3 then text will always hide...Chalmer
Hey @YunusHaznedar. Would you consider accepting my answer? The accepted answer doesn't work anymore. Having the right answer as the accepted answer could save a lot o people some time. Thanks.Tamarau
Hey, @DanXPrado thanks for sharing the solution. I have marked your answer as accepted. Happy coding.Alpenhorn
T
172

The solution using reflection doesn't work anymore because the field mShiftingMode was removed.

There's an easy way to do it now: Use Support Library 28 or higher and just add app:labelVisibilityMode="labeled" to your BottomNavigationView XML declaration.

Tamarau answered 24/7, 2018 at 6:18 Comment(3)
Working like a champ, but how to make it circular scrollable?Salvation
@ShylendraMadda I suggest you posting that as a new question since it's not related to this question.Tamarau
How is this not the default behavior... I wasted a few hours with app:showAsAction, android:visible, android:enabled and a bunch of other hacks. Thanks!Constable
T
96

UPDATE

removeShiftMode() is no longer needed, as in support library 28.0.0-alpha1 we can now add Labels.

In XML:

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

For programmatically change:

mBottomNavigationView.setLabelVisibilityMode(LabelVisibilityMode.LABEL_VISIBILITY_LABELED); 

For this to work: update the design support library to 28.0.0-alpha1

Here is a Good read

FOR OLDER SUPPORT LIBRARY:

in your bottom_bar_menu.xml.Change the showAsAction attribute

<item android:id="@id/menu_item"
android:title="text"
android:icon="@drawable/drawable_resource_name"
android:showAsAction="always|withText" />

in build.gradle:

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

BOTTOM NAVIGATIONVIEW MORE THAN 3 ITEMS: use removeShiftMode() method

in BottomNavigationViewHelper.java Use:

import android.annotation.SuppressLint;
import android.support.design.internal.BottomNavigationItemView;
import android.support.design.internal.BottomNavigationMenuView;
import android.support.design.widget.BottomNavigationView;
import java.lang.reflect.Field;

    public class BottomNavigationViewHelper {
        @SuppressLint("RestrictedApi")
        public static void removeShiftMode(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("BottomNav", "Unable to get shift mode field", e);
            } catch (IllegalAccessException e) {
                Log.e("BottomNav", "Unable to change value of shift mode", e);
            }
        }
    }

Call it using:

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

It will disable the shift animation of the title text and enable the text to be displayed.

Toughen answered 18/1, 2017 at 11:51 Comment(13)
No, it is still hiding. I tried "always" and "always|withText"Alpenhorn
I did that view from this website. medium.com/@hitherejoe/…Alpenhorn
can u try it with three item? also check your text color if it matched with the backgroundToughen
Yes, it worked out well. But I need 4 tabs not 3. How I can do that?Alpenhorn
one of ur item title is large is causing other's view to block? try with small title and drawable images..Toughen
see this line on the tutotrial you are following It’s important to note that the maximum number of items we can display is 5. This may change at any point, so it’s important to check this by using the getMaxItem() method provided by the BottomNavigationView class rather than hard-coding the value yourself.Toughen
Yeah, I noticed that. Thanks for helping guys.Alpenhorn
@Toughen Please update the answer and mention that less than 4 items are going to show the texts for all items based on the screen sizes.Appel
I have edited the answer @AjayShrestha..while the answer may not help you..it simply cannot be the reason to downvote the answer...we in stackoverflow downvote a bad answer...not a potentially good answer..Toughen
great answer, ThanksPlacoid
The reflection solution works pretty well on com.android.support:design:25.4.0, but fails on com.android.support:design:26.1.0, so I roll back the target SDK and dependencies' version a little.Exciter
the answer is updated with the latest functionality available in support library,Toughen
is it applicable for more than 5 menu items?Ironic
A
10

After scan source code of BottomNavigationView I find

mShiftingMode = mMenu.size() > 3;

in BottomNavigationMenuView.java line 265, it means while menu size more than 3, tab title wiil be hid. So if you want to show tab title you just need to get code from build and change to below.

mShiftingMode = mMenu.size() > 5;

PS: BottonNavigationView max tab count must between 3 and 5. You can get code on BottomNavigationViewNew enter image description here

Adverb answered 10/4, 2017 at 8:11 Comment(2)
I have my own CustomBottomView that extends BottomNavigationView, is there a way to set that property instead?Subtype
I don't see the line of "BottomNavigationMenuView" that is about the 3 tabs limit. Maybe the code has changed?Carmen
V
8

Create Class BottomNavigationViewHelper

import android.annotation.SuppressLint;
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 {
    @SuppressLint("RestrictedApi")
    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);
if(menuView.getChildCount()<6)
           {
            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);
        }
    }
}   

Call

    BottomNavigationView bottomNavigationView = (BottomNavigationView)findViewById(R.id.bottom_navigation);
    BottomNavigationViewHelper.disableShiftMode(bottomNavigationView); 
Vizard answered 15/12, 2017 at 12:1 Comment(1)
It has SuppressLint which solve restrictAPI annoation issueDesecrate
L
5

app:labelVisibilityMode="labeled"

Add above code under your XML file.

Example:

xmlns:app="http://schemas.android.com/apk/res-auto"


<com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_nav_view"
        ....
        ....
        app:labelVisibilityMode="labeled"/>
Lysimeter answered 14/5, 2021 at 23:10 Comment(0)
R
3

Kotlin extension function:

@SuppressLint("RestrictedApi")
fun BottomNavigationView.removeShiftMode(){
    val menuView = this.getChildAt(0) as BottomNavigationMenuView
    try {
        val shiftingMode = menuView.javaClass.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) {
        e.printStackTrace()
        Timber.tag("BottomNav").e( e, "Unable to get shift mode field")
    } catch (e: IllegalAccessException) {
        Timber.tag("BottomNav").e( e, "Unable to change value of shift mode")
    }
}
Ripley answered 24/8, 2018 at 9:45 Comment(2)
Thank you, sir. Very appreciated.Alpenhorn
item.setShiftingMode(false) is now item.setShifting(false)Fortitude
P
2

I pretty much used rafsanahmad007 answer but translate it to Kotlin. Let me share it for the future wanderers

@SuppressLint("RestrictedApi")
fun BottomNavigationView.disableShiftMode() {
    val menuView = this.getChildAt(0) as BottomNavigationMenuView
    try {
        val shiftingMode = menuView::class.java.getDeclaredField("mShiftingMode")
        shiftingMode.setAccessible(true)
        shiftingMode.setBoolean(menuView, false)
        shiftingMode.setAccessible(false)
        for (i in 0..(menuView.childCount - 1)) {
            val item = menuView.getChildAt(i) as BottomNavigationItemView
            item.setShiftingMode(false)
            // set once again checked value, so view will be updated
            item.setChecked(item.getItemData().isChecked())
        }
    } catch (e: NoSuchFieldException) {
        Timber.e("Unable to get shift mode field")
    } catch (e: IllegalAccessException) {
        Timber.e("Unable to change value of shift mode")
    }
}
Passed answered 4/7, 2018 at 12:51 Comment(2)
This solution is not longer valid, the accepted solution is correct by @DanXPradoRipley
Thx for letting me knowPassed
T
0

This works for me in API 26 :

 navigation = (BottomNavigationView) view.findViewById(R.id.bottom_navigation);


     try{disableShiftMode(navigation);}catch(Exception ew){}

Make this method in your Activity or Fragment where you want to call:

 @SuppressLint("RestrictedApi")
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);
            item.setShiftingMode(false);

            item.setChecked(item.getItemData().isChecked());
        }
    } catch (NoSuchFieldException e) {

    } catch (IllegalAccessException e) {

    }
}
Telugu answered 22/12, 2018 at 11:58 Comment(0)
D
0

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....

Discussant answered 23/3, 2019 at 5:0 Comment(0)
F
0

quick fixed just add app:labelVisibilityMode="labeled" in xml

<android.support.design.widget.BottomNavigationView
    android:id="@+id/bottom_navigation"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    app:itemBackground="@color/colorPrimary"
    app:itemIconTint="@drawable/bottom_navigation_color_selector"
    app:itemTextColor="@drawable/bottom_navigation_color_selector"
    app:labelVisibilityMode="labeled"
    app:menu="@menu/menu_bottom_navigation" />

Note

  implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:design:28.0.0'
implementation 'com.android.support:support-v4:28.0.0'
Foreland answered 23/5, 2019 at 10:55 Comment(0)
H
0

One thing to note even though it does not apply in this case.

This pattern can be used when you have between 3 and 5 top-level destinations to navigate to.

To enable the icon title to display do the following:

  1. Make sure your menu (bottom_navigation_menu) item XML is structured as follows:-

    <item
        android:id="@+id/action_home"
        android:enabled="true"
        android:icon="@drawable/ic_action_home"
        android:title="HOME"
        app:showAsAction="ifRoom"/>
    
    <item
        android:id="@+id/action_favourites"
        android:enabled="true"
        android:icon="@drawable/ic_action_favourite"
        android:title="FAVOURITES"
        app:showAsAction="ifRoom"/>
    
    <item
        android:id="@+id/action_basket"
        android:enabled="true"
        android:icon="@drawable/ic_action_basket"
        android:title="BASKET"
        app:showAsAction="ifRoom"/>
    

  2. Add the following to the BottomNavigationView code app:labelVisibilityMode="labeled"

<com.google.android.material.bottomnavigation.BottomNavigationView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom"
    android:background="@android:color/white"
    app:itemIconTint="@android:color/black"
    app:itemTextColor="@android:color/black"
    app:menu="@menu/bottom_navigation_menu"
    app:labelVisibilityMode="labeled"/>

Hagiolatry answered 7/1, 2020 at 14:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.