RecyclerView(三)——添加分隔线

RecyclerView中有一个默认的DividerItemDecoration,用于给RecyclerView添加分割线,实现方法如下

recyclerView.addItemDecoration(new DividerItemDecoration(MainActivity.this));//setItemDecoration()方法用于为RecyclerView子项的一些装饰(我个人的理解)
然后翻下DividerItemDecoration的原码


可以看到这个类是继承了RecyclerView.ItemDecoration这个类,并且该类中主要重写了onDraw()和getItemOffset()方法,从这两个方法的名字可以看出一个适用于绘制,一个是用于获取偏移量。

RecyclerView提供的默认的DividerItemDecoration类只能用于绘制线性布局方式的分割线,无法实现网格的分隔线,通过上面的代码可以看出,我们若是自己编写一个类继承RecyclerView.ItemDecoration也是可以实现为RecyclerView绘制分隔线的效果


接下来上代码

MainActivity.java中的代码只截部分


MyGridItemDecoration类

package com.example.lsn2_materialdesign_recyclerview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.RecyclerView;
import android.view.View;

public class MyGridItemDecoration extends RecyclerView.ItemDecoration {
    private Drawable mDivider;
    private int[] attrs = new int[]{
            android.R.attr.listDivider
    };
    private int col ;

    public MyGridItemDecoration(Context context, int col){
        TypedArray typedArray = context.obtainStyledAttributes(attrs);
        mDivider = typedArray.getDrawable(0);
        typedArray.recycle();
        this.col = col;
    }



    @Override
    //在getItemOffset()方法中设置了分割线的宽度,之后会在onDraw中进行绘制,这里面会为每一条边设置在画布上显示的位置
    public void onDraw(Canvas c,RecyclerView parent, RecyclerView.State state){
        drawVertical(c, parent);//绘制垂直分隔线
        drawHorizontal(c, parent);//绘制水平分隔线
        super.onDraw(c, parent, state);
    }

    private void drawVertical(Canvas c, RecyclerView parent) {

        int childCount = parent.getChildCount();//获取RecyclerView中子项的数目,然后遍历
        for(int i=0;i<childCount; i++){
            if((i+1) % col != 0){//判断是否为最后一列,最后一列不用画垂直分隔线
                View child = parent.getChildAt(i);
                RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();//获取子项的布局参数

                int top = child.getTop() + params.topMargin;//设置分隔线顶部的位置
                int bottom = child.getBottom() + params.bottomMargin;//设置分隔线底部的位置,绘制的是垂直分隔线,顶部到底部的距离就是分隔线的高度
                int left = child.getRight() - params.rightMargin - 5;//设置分隔线左边的位置,这里我减了个5,为了让分割线不是贴着子项的左边,我在布局文件中没有设置margin。
                int right = left + mDivider.getIntrinsicWidth();//设置分隔线右边的位置,左边到右边的距离就是分隔线的粗细值

                mDivider.setBounds(left, top, right, bottom);//设置绘画的边界
                mDivider.draw(c);
            }
        }
    }

    //水平分隔线
    private void drawHorizontal(Canvas c, RecyclerView parent) {
        //水平分隔线的起始点就是子项的左边的起始点,右边起始点就是子项右边的结束点
        int left = parent.getPaddingLeft();
        int right = parent.getWidth() - parent.getPaddingRight();

        int childCount = parent.getChildCount();
        for(int i=0; i<childCount; i++){
            if(childCount - i > col){//判断是否为最后一行,最后一行不用画水平分隔线
                View child = parent.getChildAt(i);
                RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
                //每个子项的线面会画一条分隔线,因此分隔线上边其实就是子项的底部位置再加上底部的margin,若是在Y轴方向上有偏移量,则也要加上
                int top = child.getBottom() + params.bottomMargin + Math.round(ViewCompat.getTranslationY(child));
                //底部的位置就是分隔线的上边加上分隔线的粗细值
                int bottom = top + mDivider.getIntrinsicHeight();

                mDivider.setBounds(left, top, right, bottom);
                mDivider.draw(c);
            }
        }
    }


    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state){
        //RecyclerView的子项其实就是一个矩形区域,set方法就是设置了这个矩形区域每个边框线的粗细,参数依次是左、上、右、下
        outRect.set(0, 0, mDivider.getIntrinsicWidth(), mDivider.getIntrinsicHeight());
    }

}

运行结果如下:


其实我们还可以用ItemDecoration来干些别的东西的,这里只是讲了ItemDecoration的简单用法,以后若是有需要在研究别的,若是有什么问题欢迎提问哦

阅读更多 登录后自动展开
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页