目录:
1.概述
2.分割线绘制方式与原理
3.通过paint绘制垂直布局/
水平布局
分割线
4.
通过修改系统主题绘制垂直布局/
水平布局
分割线
1.概述
RecyclerView不像ListView可以通过android:divider=""布局属性来设置分割线,它需要我们去继承RecyclerView.ItemDecoration类去自己绘制。
2.分割线绘制方式与原理
2.1 走近RecyclerView.ItemDecoration
先来看看我要用到的3个方法
/*
* 该方法实现通过canvas参数绘制分割线
* */
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state){
}
/*
* 该方法与上一方法雷同,实现通过canvas参数绘制分割线,
* 与onDraw()不同的点在于onDrawOver()是在item view绘制之后调用
* */
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
}
/*
* 设置item偏移,在item之间添加分割线,后面一个item就需要往后偏移分割线的宽度
* */
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
}
这三个方法中onDraw()和onDrawOver()基本作用基本相同,就是绘制我们的分割线,区别在于
onDraw()在item view绘制之前调用,而
onDrawOver()在item View绘制之后调用;最后剩下的getItemOffsets()的作用主要是设置分割线的高度,设置item的偏移值。
2.2 onDraw()的中的分割线绘制
其实分割线的绘制就是绘制一个稍微细一点的矩形而已,我们已知的实现方式就是通过画笔(Paint)绘制,或者绘制定义好的图片。而在布局中绘制的时候要根据每一条分割线的不同位置,来计算出每一条分割线的上下左右坐标点值,最终通过draw()绘制。我们绘制的难点其实主要就是计算每条分割线的上下左右坐标。我抽取了一段通过Paint绘制垂直布局分割线的代码:
/*
* paint绘制垂直方向布局的分割线
* */
private void drawVerticalDivider(Canvas c, RecyclerView parent) {
//计算item布局左边的x坐标没,也就是分割线的左边x坐标
final int left=parent.getPaddingLeft();
//计算item右边的x坐标,也就是分割线的右边x坐标
final int right=parent.getMeasuredWidth()-parent.getPaddingRight();
//获取item数量
final int item_num=parent.getChildCount();
//循环绘制item分割线
for (int i=0;i<item_num;i++){
View child_item=parent.getChildAt(i);
//获取到当前item的布局参数
RecyclerView.LayoutParams layoutParams= (RecyclerView.LayoutParams) child_item.getLayoutParams();
//绘制分割线的起始y坐标
int top=child_item.getBottom()+layoutParams.bottomMargin;
//绘制分割线底部y坐标
int bottom=top+divider_size;
//开始绘制
c.drawRect(left,right,top,bottom,paint);
}
}
可以看到垂直方向的分割线绘制,左边起点坐标值left就等于父组件也就是RecyclerView左内边距,右边结束坐标就是RecyclerView宽度减去右内边距,这两个都比较简单,而下面分割线顶部开始位置坐标值和底部结束坐标值的计算就相对来说要难一点了,他需要我们根据item不同的位置去计算。
顶部和底部的计算,首先我们要获取到RecyclerView有多少个子item项,然后根据不同的item获取他们相对的布局参数以此来计算top和bottom的值。恩,大概就是这样,不晓得描述清楚没有。
2.3 getItemOffsets()设置偏移
getItemOffsets()相当于设置绘制分割线后,下一item的偏移值,水平布局的RecyclerView即为向右偏移一个分割线的宽度;垂直布局的RecyclerView即为向下偏移一个分割线的宽度,即set
(
int
left,
int
top,
int
right,
int
bottom)
设置为set(0,0,divider_size,0)以及
set(0,0,0,divider_size)
3.通过paint绘制垂直布局/水平布局分割线
3.1 效果截图
(1) 不设置分割线效果 (2)设置分割线的效果
3.2 主布局文件activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/divider_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
3.3 单个数据项布局文件divider_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:background="@color/colorAccent"
android:layout_height="match_parent">
<TextView
android:id="@+id/item_text"
android:textSize="20dp"
android:textColor="#fff"
android:gravity="center"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="88dp" />
</RelativeLayout>
3.4 主布局Java类DividerItemActivity.java
package com.example.recyclerviewdemo;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
/**
* Created by elimy on 2017-01-02.
*/