android menu分割线,给 NavigationView 的Menu的分割线 设置高度和颜色

最近遇到了一个问题,是给DrawerLayout的NavigationView的导航添加分割线,项目中的左侧导航栏之前的实现是用系统Menu的方式来实现的,需求要给导航添加分割线,并且自定义颜色和高度,查看文档虽然能通过给menu通过group加id的方式添加分割线 ,代码如下:

android:id="@+id/group1"

android:checkableBehavior="single">

android:id="@+id/nav_camera"

android:icon="@drawable/ic_menu_camera"

android:title="Import" />

android:id="@+id/nav_gallery"

android:icon="@drawable/ic_menu_gallery"

android:title="Gallery" />

android:id="@+id/group2"

android:checkableBehavior="single">

android:id="@+id/nav_slideshow"

android:icon="@drawable/ic_menu_slideshow"

android:title="Slideshow" />

android:id="@+id/nav_manage"

android:icon="@drawable/ic_menu_manage"

android:title="Tools" />

android:id="@+id/nav_share"

android:icon="@drawable/ic_menu_share"

android:title="Share" />

android:id="@+id/nav_send"

android:icon="@drawable/ic_menu_send"

android:title="Send" />

显示如下图:

f455141c9d59?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

Paste_Image.png

但是设计不喜欢这个线条啊,很粗啊,颜色不好看啊!好吧改!不过在NavigationView上没有找到可以订制的属性!然后查看NavigationView的源代码,发现 左侧栏的布局是通过NavigationMenuPresenter这个类来实现的,通过查看NavigationMenuPresenter的代码发现了 design_navigation_item_separator.xml 这个布局:

android:layout_width="match_parent"

android:layout_height="wrap_content">

android:layout_height="1dp"

android:background="?android:attr/listDivider"/>

发现颜色是可以通过在主题里通过listDivider属性来配置,但是高度固定1dp了,View 没有ID说明就没有考虑这个高度,怎么改?

看看NavigationMenuPresenter的具体实现吧,左侧栏整个布局是通过RecyclerView 来实现的,通过不同的 View 的 TYPE 类型来加载不同的布局!那么是不是可以从 RecyclerView 的 addOnChildAttachStateChangeListener 方法入手?

实践出真知!

我们可以先通过反射得到RecyclerView:

Field fieldByPressenter = navigationView.getClass().getDeclaredField("mPresenter");

fieldByPressenter.setAccessible(true);

NavigationMenuPresenter menuPresenter = (NavigationMenuPresenter) fieldByPressenter.get(navigationView);

Field fieldByMenuView = menuPresenter.getClass().getDeclaredField("mMenuView");

fieldByMenuView.setAccessible(true);

final NavigationMenuView mMenuView = (NavigationMenuView) fieldByMenuView.get(menuPresenter);

mMenuView就是RecyclerView,剩下的是给其注册addOnChildAttachStateChangeListener监听,每加载一个view 就获取它的ViewHolder,通过判断ViewHolder是否是SeparatorViewHolder(是分割线的独有ViewHolder)的实例,来确定分割线View,然后想怎么操作就怎么操作!完整代码如下:

public static void setNavigationMenuLineStyle(NavigationView navigationView, @ColorInt final int color, final int height) {

try {

Field fieldByPressenter = navigationView.getClass().getDeclaredField("mPresenter");

fieldByPressenter.setAccessible(true);

NavigationMenuPresenter menuPresenter = (NavigationMenuPresenter) fieldByPressenter.get(navigationView);

Field fieldByMenuView = menuPresenter.getClass().getDeclaredField("mMenuView");

fieldByMenuView.setAccessible(true);

final NavigationMenuView mMenuView = (NavigationMenuView) fieldByMenuView.get(menuPresenter);

mMenuView.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() {

@Override

public void onChildViewAttachedToWindow(View view) {

RecyclerView.ViewHolder viewHolder = mMenuView.getChildViewHolder(view);

if (viewHolder != null && "SeparatorViewHolder".equals(viewHolder.getClass().getSimpleName()) && viewHolder.itemView != null) {

if (viewHolder.itemView instanceof FrameLayout) {

FrameLayout frameLayout = (FrameLayout) viewHolder.itemView;

View line = frameLayout.getChildAt(0);

line.setBackgroundColor(color);

line.getLayoutParams().height = height;

line.setLayoutParams(line.getLayoutParams());

}

}

}

@Override

public void onChildViewDetachedFromWindow(View view) {

}

});

} catch (Throwable e) {

e.printStackTrace();

}

}

效果图如下:

f455141c9d59?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

Paste_Image.png

再来个更直观的图:

f455141c9d59?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

Paste_Image.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值