How to increase width of BottomNavigationView menu. Below is the current scenario. I am not able to increase the width to complete screen.
Menu.xml
That is doable (Even without reflection). But it will againts default design specs, and I wil suggest you to go with default design specs.
Now coming to my solution...
Define below dimensions into dimens.xml
. These dimensions should be in values
, values-large
, values-large-land
and 600dp
can be increased to 1000dp
or more in values-large
, values-large-land
, if in tablet you are not seeing this change.
<resources xmlns:tools="http://schemas.android.com/tools">
<dimen name="design_bottom_navigation_item_max_width" tools:override="true">600dp</dimen>
<dimen name="design_bottom_navigation_active_item_max_width" tools:override="true">600dp</dimen>
</resources>
And thats it!!! Result will be like
It's not a mazic.
Why dimensions has been added with such name and value is 600dp
Both dimensions is being used by BottomNavigationMenuView.java
(which is the class being used to represent menu in BottomNavigationView
).
Below is code
public BottomNavigationMenuView(Context context, AttributeSet attrs) {
super(context, attrs);
...
mInactiveItemMaxWidth = res.getDimensionPixelSize(
R.dimen.design_bottom_navigation_item_max_width);
....
mActiveItemMaxWidth = res.getDimensionPixelSize(
R.dimen.design_bottom_navigation_active_item_max_width);
.....
}
Now these values is being used to create view with fixed width, as below
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
....
if (mShiftingMode) {
final int inactiveCount = count - 1;
final int activeMaxAvailable = width - inactiveCount * mInactiveItemMinWidth;
final int activeWidth = Math.min(activeMaxAvailable, mActiveItemMaxWidth);
final int inactiveMaxAvailable = (width - activeWidth) / inactiveCount;
final int inactiveWidth = Math.min(inactiveMaxAvailable, mInactiveItemMaxWidth);
...
} else {
final int maxAvailable = width / count;
final int childWidth = Math.min(maxAvailable, mActiveItemMaxWidth);
.....
}
....
}
To use value of activeMaxAvailable
always, I set a dummy value to mActiveItemMaxWidth
(in dimens above). So activeWidth
will have
value of activeMaxAvailable
. Same rule apply for inactiveWidth
.
So when you build project, design_bottom_navigation_item_max_width
and design_bottom_navigation_active_item_max_width
defined
into design-support-lib, will be replaced by dimensions defined by us.
Code verified on maximum supported options (5 max) also.
According to the BottomNavigationView specs: https://material.io/guidelines/components/bottom-navigation.html#specs-figure-caption-17
Your navigation is correctly, but if anyway you want to expand the padding between the elements I recommend that you create your own bottom navigation using something like FlexBoxLayout: https://github.com/google/flexbox-layout
i dont remember where i found this solution exactly but you use this helper class to disable item shifting for BottomNavigation using Java Reflection :
import android.content.Context;
import android.graphics.Typeface;
import android.support.design.internal.BottomNavigationItemView;
import android.support.design.internal.BottomNavigationMenuView;
import android.support.design.widget.BottomNavigationView;
import android.util.Log;
import android.widget.TextView;
import java.lang.reflect.Field;
public class BottomNavigationViewHelper {
public static void disableShiftMode(Context context,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);
Field LargeText = item.getClass().getDeclaredField("mLargeLabel");
LargeText.setAccessible(true);
Field SmallText = item.getClass().getDeclaredField("mSmallLabel");
SmallText.setAccessible(true);
// TextView SmallTextView =(TextView) SmallText.get(item);
// TextView LargeTextView =(TextView) LargeText.get(item);
// Typeface tf = TypefaceHelper.getTypeface(context);
// SmallTextView.setTypeface(tf);
// LargeTextView.setTypeface(tf);
//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);
}
}
}