Android开发:NavigationView中Menu的分割线的相关设置

为DrawerLayout的NavigationView的导航添加分割线,项目中的左侧导航栏原先的实现是

用系统Menu的方式来实现的,需求要给导航添加分割线,并且自定义颜色和高度,查看文档,

虽然能通过给menu通过group加id的方式添加分割线 ,代码如下:

[plain]  view plain  copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <menu xmlns:android="http://schemas.android.com/apk/res/android">  
  3.   
  4.     <group  
  5.         android:id="@+id/group1"  
  6.         android:checkableBehavior="single">  
  7.         <item  
  8.             android:id="@+id/nav_camera"  
  9.             android:icon="@drawable/ic_menu_camera"  
  10.             android:title="Import" />  
  11.         <item  
  12.             android:id="@+id/nav_gallery"  
  13.             android:icon="@drawable/ic_menu_gallery"  
  14.             android:title="Gallery" />  
  15.     </group>  
  16.     <group  
  17.         android:id="@+id/group2"  
  18.         android:checkableBehavior="single">  
  19.         <item  
  20.             android:id="@+id/nav_slideshow"  
  21.             android:icon="@drawable/ic_menu_slideshow"  
  22.             android:title="Slideshow" />  
  23.         <item  
  24.             android:id="@+id/nav_manage"  
  25.             android:icon="@drawable/ic_menu_manage"  
  26.             android:title="Tools" />  
  27.     </group>  
  28.     <group android:id="@+id/group3">  
  29.         <item  
  30.             android:id="@+id/nav_share"  
  31.             android:icon="@drawable/ic_menu_share"  
  32.             android:title="Share" />  
  33.         <item  
  34.             android:id="@+id/nav_send"  
  35.             android:icon="@drawable/ic_menu_send"  
  36.             android:title="Send" />  
  37.     </group>  
  38.   
  39. </menu>  

如图所示:


但是设计不喜欢这个线条啊,很粗啊,颜色不好看啊!好吧改!不过在NavigationView上没

有找到可以订制的属性!然后查看NavigationView的源代码,发现 左侧栏的布局是通过

NavigationMenuPresenter这个类来实现的,通过查看NavigationMenuPresenter的代码发现了 

design_navigation_item_separator.xml 这个布局:

[plain]  view plain  copy
  1. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.              android:layout_width="match_parent"  
  3.              android:layout_height="wrap_content">  
  4.   
  5.     <View android:layout_width="match_parent"  
  6.           android:layout_height="1dp"  
  7.           android:background="?android:attr/listDivider"/>  
  8.   
  9. </FrameLayout>  

发现颜色是可以通过在主题里通过listDivider属性来配置,但是高度固定1dp了,View 没有ID说明

就没有考虑这个高度,怎么改? 看看NavigationMenuPresenter的具体实现吧,左侧栏整个布局

是通过RecyclerView 来实现的,通过不同的 View 的 TYPE 类型来加载不同的布局!那么是不是

可以从 RecyclerView 的 addOnChildAttachStateChangeListener 方法入手? 实践出真知! 我们可以先通

过反射得到RecyclerView:

[plain]  view plain  copy
  1. Field fieldByPressenter = navigationView.getClass().getDeclaredField("mPresenter");  
  2.             fieldByPressenter.setAccessible(true);  
  3.             NavigationMenuPresenter menuPresenter = (NavigationMenuPresenter) fieldByPressenter.get(navigationView);  
  4.             Field fieldByMenuView = menuPresenter.getClass().getDeclaredField("mMenuView");  
  5.             fieldByMenuView.setAccessible(true);  
  6.             final NavigationMenuView mMenuView = (NavigationMenuView) fieldByMenuView.get(menuPresenter);  

mMenuView就是RecyclerView,剩下的是给其注册addOnChildAttachStateChangeListener监听,每

加载一个view 就获取它的ViewHolder,通过判断ViewHolder是否是SeparatorViewHolder(是分割线的

独有ViewHolder)的实例,来确定分割线View,然后想怎么操作就怎么操作!完整代码如下:

[plain]  view plain  copy
  1. public static void setNavigationMenuLineStyle(NavigationView navigationView, @ColorInt final int color, final int height) {  
  2.         try {  
  3.             Field fieldByPressenter = navigationView.getClass().getDeclaredField("mPresenter");  
  4.             fieldByPressenter.setAccessible(true);  
  5.             NavigationMenuPresenter menuPresenter = (NavigationMenuPresenter) fieldByPressenter.get(navigationView);  
  6.             Field fieldByMenuView = menuPresenter.getClass().getDeclaredField("mMenuView");  
  7.             fieldByMenuView.setAccessible(true);  
  8.             final NavigationMenuView mMenuView = (NavigationMenuView) fieldByMenuView.get(menuPresenter);  
  9.             mMenuView.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() {  
  10.                 @Override  
  11.                 public void onChildViewAttachedToWindow(View view) {  
  12.                     RecyclerView.ViewHolder viewHolder = mMenuView.getChildViewHolder(view);  
  13.                     if (viewHolder != null && "SeparatorViewHolder".equals(viewHolder.getClass().getSimpleName()) && viewHolder.itemView != null) {  
  14.                         if (viewHolder.itemView instanceof FrameLayout) {  
  15.                             FrameLayout frameLayout = (FrameLayout) viewHolder.itemView;  
  16.                             View line = frameLayout.getChildAt(0);  
  17.                             line.setBackgroundColor(color);  
  18.                             line.getLayoutParams().height = height;  
  19.                             line.setLayoutParams(line.getLayoutParams());  
  20.                         }  
  21.                     }  
  22.                 }  
  23.   
  24.                 @Override  
  25.                 public void onChildViewDetachedFromWindow(View view) {  
  26.   
  27.                 }  
  28.             });  
  29.         } catch (Throwable e) {  
  30.             e.printStackTrace();  
  31.         }  
  32.     }  

效果图如下:


再来个更直观的图:

猜你喜欢

转载自blog.csdn.net/qq_41405257/article/details/80710028