BottomNavigationView 中的菜单项未居中

Gér*_*ard 4 java xml bottomnavigationview

我有一个底部导航视图,没有图标,只有文本字段。

我想垂直和水平居中文本并为不同的状态添加一个突出显示:

topnavigationview.setItemBackgroundResource(R.drawable.mainactivitybackgroundhighlight_top);
Run Code Online (Sandbox Code Playgroud)

使用 xml 代码:

<?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>
Run Code Online (Sandbox Code Playgroud)

该视图包含如下:

<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" />
Run Code Online (Sandbox Code Playgroud)

然而,它现在看起来像这样:

在此处输入图片说明

如您所见,突出显示并没有覆盖菜单的一半,更像是它的 40%;选择右手项目时相同 - 尽管宽度设置为match_parent。

文本也不是垂直居中,也不是水平居中;

1) 如何在布局中垂直居中菜单文本?

2) 如何让两个菜单项都占据导航视图的 50%?这将使文本水平居中并使突出显示按预期占据 50%。

Ben*_* P. 6

真正的答案是:不要这样做。您正在尝试使用一个支持设计库组件,该组件被创建为具有特定的外观和感觉,但您希望以不同的方式使其外观和感觉。您应该创建自己的视图以按照您想要的方式行事。

但...

1) 如何在布局中垂直居中菜单文本?

深入研究 for 的实现BottomNavigationView,我们最终发现菜单项由BottomNavigationItemView对象(派生自FrameLayout)表示,它们使用这种布局:https : //github.com/dandar3/android-support-design/blob/master/res/layout /design_bottom_navigation_item.xml

因此,我们可以创建一个方法来调整标签视图的父级上的重力和填充,使它们显示为居中:

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));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

2) 如何让两个菜单项都占据导航视图的 50%?

每个菜单项的宽度由BottomNavigationMenuView类中的以下代码约束:

mActiveItemMaxWidth = res.getDimensionPixelSize(
        R.dimen.design_bottom_navigation_active_item_max_width);
Run Code Online (Sandbox Code Playgroud)

没有修改这个值的好方法,但我们可以使用反射来做到这一点:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

一旦你在你的活动中拥有这些方法,你就可以这样写:

BottomNavigationView nav = findViewById(R.id.top_navigation_view);
adjustGravity(nav);
adjustWidth(nav);
Run Code Online (Sandbox Code Playgroud)

请注意,因为这些方法中的每一个都依赖于 的内部实现细节BottomNavigationView,所以当您更新支持/设计库时,它们总是会受到破坏。