Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add margins to navigation item in BottomNavigationView

I have a BottomNavigationView which I instantiate like this:

BottomNavigationView navigationView = findViewById(R.id.bottom_navigation);
navigationView.setOnNavigationItemSelectedListener(this);

/menu/menu.xml looks like this:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/first_id"
        android:icon="@drawable/home_icon"
        android:title="Item" />

    <item
        android:id="@+id/second_id"
        android:icon="@drawable/home_icon"
        android:title="Item" />

    <item
        android:id="@+id/third_id"
        android:icon="@drawable/home_icon"
        android:title="Item" />

    <item
        android:id="@+id/fourth_id"
        android:icon="@drawable/home_icon"
        android:title="Item" />
</menu>

And /drawable/home_icon looks like this:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportHeight="24.0"
    android:viewportWidth="24.0">
    <path
        android:fillColor="#FFFFF0"
        android:pathData="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"
        android:strokeColor="#FFFFF0"
        android:strokeWidth="1" />
</vector>

As you can see, I have borders around the buttons of the navigation items, however, the borders touch each other. Therefore I would like to add a margin between the menu buttons. How can I do this?

enter image description here

As you can also see from the screenshot, I am preventing shifting mode. I do this by calling

BottomNavigationViewHelper.removeShiftMode(navigationView);

using code from here.

The borders around the buttons have been added like this:

int stateListDrawable = drawableStateLists.get(currentFragment);
navigationView.setItemBackgroundResource(stateListDrawable);

while stateListDrawable refers to a StateListDrawable which changes when a different menu button is pressed. The StateListDrawable refers to an xml selector which in turn refers to an xml shape like this, for example:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners android:radius="5dp"/>
    <stroke
        android:width="2dp"
        android:color="@color/intro"/>
</shape>
like image 867
kalabalik Avatar asked Dec 11 '17 23:12

kalabalik


1 Answers

After carefully inspecting and experimenting with sources, I've came up with the most basic and legitimate solution - inset the drawable itself.

Having declared the xml drawable like this:

<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:insetLeft="10dp"
    android:insetRight="10dp">
    <shape android:shape="rectangle">
        <corners android:radius="5dp" />
        <stroke
            android:width="2dp"
            android:color="#ffffff" />
    </shape>
</inset>

You'll get following output:

enter image description here

I strived to find a programmatic solution first, but turns out there does not exist that much seams in order to do that (at least that're my findings). To be precise each item's layout params are instance of ViewGroup.LayoutParams. Had the item be laid out with ViewGroup.MarginLayoutParams, then there would be a possibility to set a margin to each item individually. Until then the background drawable xml should be applied inset instead.

like image 57
azizbekian Avatar answered Sep 22 '22 04:09

azizbekian