Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Menu items in BottomNavigationView not centered

I have a bottom navigation view that has no icons, only text fields.

I want to center the text vertically & horizontally and added a highlight for the different states:

topnavigationview.setItemBackgroundResource(R.drawable.mainactivitybackgroundhighlight_top);

with the xml code:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/blau" android:state_pressed="true" />
    <item android:drawable="@color/blau" android:state_checked="true" />
    <item android:drawable="@color/dunkelgraublau" />
</selector>

The view is included like this:

<android.support.design.widget.BottomNavigationView
            android:id="@+id/top_navigation_view"
            android:layout_width="match_parent"
            android:layout_height="35dp"
            android:layout_below="@id/include4"
            android:background="@color/dunkelgraublau"
            app:itemTextColor="@color/weiß"
            app:menu="@menu/top_navigation_menu" />

however, it now looks like this:

enter image description here

as you can see the highlight does not cover half of the menu, more like 40% of it; when selecting the right hand item its the same - despite the width being set to match_parent.

the text also is neither centered vertically nor horizontally;

1) how do i center the menu text vertically within the layout?

2) how do i make it so both menu items take up 50% of the navigation view? this would center the text horizontally and make the highlight take up 50% as intended.

like image 734
Gérard Avatar asked Jan 29 '23 16:01

Gérard


1 Answers

The real answer is: don't do this. You're trying to use a support design library component that was created to look and feel a certain way, but you want to make it look and feel a different way. You should create your own view to behave the way you want.

But...

1) how do i center the menu text vertically within the layout?

Digging into the implementation for BottomNavigationView, we eventually find that the menu items are represented by BottomNavigationItemView objects (derived from FrameLayout), which use this layout: https://github.com/dandar3/android-support-design/blob/master/res/layout/design_bottom_navigation_item.xml

As such, we can create a method to adjust the gravity and padding on the label views' parent so that they appear centered:

private static void adjustGravity(View v) {
    if (v.getId() == android.support.design.R.id.smallLabel) {
        ViewGroup parent = (ViewGroup) v.getParent();
        parent.setPadding(0, 0, 0, 0);

        FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) parent.getLayoutParams();
        params.gravity = Gravity.CENTER;
        parent.setLayoutParams(params);
    }

    if (v instanceof ViewGroup) {
        ViewGroup vg = (ViewGroup) v;

        for (int i = 0; i < vg.getChildCount(); i++) {
            adjustGravity(vg.getChildAt(i));
        }
    }
}

2) how do i make it so both menu items take up 50% of the navigation view?

The width of each menu item is constrained by this code in the BottomNavigationMenuView class:

mActiveItemMaxWidth = res.getDimensionPixelSize(
        R.dimen.design_bottom_navigation_active_item_max_width);

There's no good way to modify this value, but we can do so using reflection:

private static void adjustWidth(BottomNavigationView nav) {
    try {
        Field menuViewField = nav.getClass().getDeclaredField("mMenuView");
        menuViewField.setAccessible(true);
        Object menuView = menuViewField.get(nav);

        Field itemWidth = menuView.getClass().getDeclaredField("mActiveItemMaxWidth");
        itemWidth.setAccessible(true);
        itemWidth.setInt(menuView, Integer.MAX_VALUE);
    }
    catch (NoSuchFieldException e) {
        // TODO
    }
    catch (IllegalAccessException e) {
        // TODO
    }
}

Once you have these methods in your activity, you can just write this:

BottomNavigationView nav = findViewById(R.id.top_navigation_view);
adjustGravity(nav);
adjustWidth(nav);

Note that, because each of these methods relies on internal implementation details of BottomNavigationView, they are always subject to breakage when you update the support/design libraries.

like image 185
Ben P. Avatar answered Feb 05 '23 01:02

Ben P.