Android RecyclerView 详解(2)---网格布局(支持多种分割线)

上篇Android RecyclerView 详解(1)—线性布局
记录了下RecyclerView的使用方法,并且讲述了线性布局列表的使用方法,在此基础上加上了万能分割线,支持颜色分割线和图片分割线,同时支持对分割线设置线宽。
这篇是总结一下网格布局的使用,同样也支持两种分割线和线宽的设置。

主要的相关类:

1. RecyclerView.Adapter

2. GridLayoutManager 网格布局管理器

3. RecycleView.ItemDecoration 分割线

下面就直接通过一个例子来展示:

先上效果图:

(1) 颜色分割线

这里写图片描述

看起来还不错吧,根据item的数量去显示格子,当然如果你需要的样式不是三列,这个很简单,只需要在设置
GridLayoutManager的时候设置相应的列数即可,即:

mManagerLayout = new GridLayoutManager(getActivity(), 3);

(2) 图片分割线

这里写图片描述

可能有人会说你的列表四周都有分割线,其实在不做特殊处理时左边和上面默认是没有分割线的。后面我会加上四周没有分割线的,其实这两种形式在实际开发中都是常见的,先来看四周都有边线的。

由于RecycleView是高度解耦的控件,绘制分割线只和 RecycleView.ItemDecoration 有关,所以我们只需关心怎么去继承 RecycleView.ItemDecoration 去实现我们所需的分割线,如下:

这里需要说明的是:颜色分割线和图片分割线原理是完全一样的,图片分割线只是将一张很细的图片传入即可。

public class GridDivider extends RecyclerView.ItemDecoration {
    private Drawable mDividerDarwable;
    private int mDividerHight = 1;
    private Paint mColorPaint;
    public final int[] ATRRS = new int[]{android.R.attr.listDivider};

    public GridDivider(Context context) {
        final TypedArray ta = context.obtainStyledAttributes(ATRRS);
        this.mDividerDarwable = ta.getDrawable(0);
        ta.recycle();
    }

    /*
     int dividerHight  分割线的线宽
     int dividerColor  分割线的颜色
     */
    public GridDivider(Context context, int dividerHight, int dividerColor) {
        this(context);
        mDividerHight = dividerHight;
        //绘制颜色分割线的画笔
        mColorPaint = new Paint();
        mColorPaint.setColor(dividerColor);
    }

    /*
     int dividerHight  分割线的线宽
     Drawable dividerDrawable  图片分割线
     */
    public GridDivider(Context context, int dividerHight, Drawable dividerDrawable) {
        this(context);
        mDividerHight = dividerHight;
        mDividerDarwable = dividerDrawable;
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state);
        //画水平和垂直分割线
        drawHorizontalDivider(c, parent);
        drawVerticalDivider(c, parent);
    }

    public void drawVerticalDivider(Canvas c, RecyclerView parent) {
        // 这里传入的parent是recycleview,通过它我们可以获取列表的所有的元素,
        // 这里我们遍历列表中的每一个元素,对每一个元素绘制垂直分割线
        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            //获取当前item布局参数,通过它可以知道该item的精确位置,我们通过这个位置去绘制它的分割线
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

            final int top = child.getTop() - params.topMargin;
            final int bottom = child.getBottom() + params.bottomMargin;

            int left = 0;
            int right = 0;

            //左边第一列,
            if ((i % 3) == 0) {
                //item左边分割线
                left = child.getLeft();
                right = left + mDividerHight;
                mDividerDarwable.setBounds(left, top, right, bottom);
                mDividerDarwable.draw(c);
                if (mColorPaint != null) {//如果是颜色分割线
                    c.drawRect(left, top, right, bottom, mColorPaint);
                }
                //item右边分割线
                left = child.getRight() + params.rightMargin - mDividerHight;
                right = left + mDividerHight;
            } else {
                //非左边第一列
                left = child.getRight() + params.rightMargin - mDividerHight;
                right = left + mDividerHight;
            }
            //画分割线
            mDividerDarwable.setBounds(left, top, right, bottom);
            mDividerDarwable.draw(c);
            if (mColorPaint != null) {
                c.drawRect(left, top, right, bottom, mColorPaint);
            }
        }
    }
    //....水平分割线与垂直分割线类似,完整代码见下。
}

下面是完整代码:

1. MainActivity

public class MainActivity extends AppCompatActivity {

    private GridFragment mGridFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //网格
        mGridFragment = new GridFragment();
        getFragmentManager().beginTransaction().replace(R.id.activity_main, mGridFragment).commit();
    }

activity_main

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</FrameLayout>

2. GridFragment

public class GridFragment extends Fragment implements View.OnClickListener{

    private RecyclerView mRecycleViewDrawable;
    private RecyclerView mRecycleViewColor;
    private LinearLayoutManager mManagerColor;
    private LinearLayoutManager mManagerDrawable;
    private List<String> mData;
    private Button mDrawable;
    private Button mColor;
    private MyRecycleViewAdapter mRecycleViewAdapter;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_grid_layout, container, false);
        mRecycleViewDrawable = (RecyclerView) view.findViewById(R.id.recycleview_drawable);
        mRecycleViewColor = (RecyclerView) view.findViewById(R.id.recycleview_color);

        mDrawable = (Button) view.findViewById(R.id.btn_drawable);
        mDrawable.setOnClickListener(this);
        mColor = (Button) view.findViewById(R.id.btn_color);
        mColor.setOnClickListener(this);

        //设置颜色分割线
        mManagerColor = new GridLayoutManager(getActivity(), 3);
        mRecycleViewColor.setLayoutManager(mManagerColor);
        mRecycleViewColor.addItemDecoration(new GridDivider(getActivity(), 20, this.getResources().getColor(R.color.colorAccent)));

        //设置图片分割线
        mManagerDrawable = new GridLayoutManager(getActivity(), 3);
        mRecycleViewDrawable.setLayoutManager(mManagerDrawable);
        Drawable drawable = ContextCompat.getDrawable(getActivity(), R.mipmap.divider);
        mRecycleViewDrawable.addItemDecoration(new GridDivider(getActivity(), 20, drawable));

        //初始化数据
        mData = new ArrayList<String>();
        initData(mData);
        mRecycleViewAdapter = new MyRecycleViewAdapter(getActivity(), R.layout.item_grid_recycleview, mData);

        mRecycleViewColor.setAdapter(mRecycleViewAdapter);
        mRecycleViewDrawable.setAdapter(mRecycleViewAdapter);

        return view;
    }

    private void initData(List<String> dataList) {
        for (int i = 0; i < 16; i++) {
            dataList.add("item" + i);
        }
    }

    @Override
    public void onClick(View view) {
        int id = view.getId();
        switch (id){
            case R.id.btn_drawable:
                mRecycleViewColor.setVisibility(View.INVISIBLE);
                mRecycleViewDrawable.setVisibility(View.VISIBLE);
                break;

            case R.id.btn_color:
                mRecycleViewColor.setVisibility(View.VISIBLE);
                mRecycleViewDrawable.setVisibility(View.INVISIBLE);
                break;
        }
    }
}

3.分割线 GridDivider

直接继承 RecyclerView.ItemDecoration

public class GridDivider extends RecyclerView.ItemDecoration {

    private Drawable mDividerDarwable;
    private int mDividerHight = 1;
    private Paint mColorPaint;


    public final int[] ATRRS = new int[]{android.R.attr.listDivider};

    public GridDivider(Context context) {
        final TypedArray ta = context.obtainStyledAttributes(ATRRS);
        this.mDividerDarwable = ta.getDrawable(0);
        ta.recycle();
    }

    /*
     int dividerHight  分割线的线宽
     int dividerColor  分割线的颜色
     */
    public GridDivider(Context context, int dividerHight, int dividerColor) {
        this(context);
        mDividerHight = dividerHight;
        mColorPaint = new Paint();
        mColorPaint.setColor(dividerColor);
    }

    /*
     int dividerHight  分割线的线宽
     Drawable dividerDrawable  图片分割线
     */
    public GridDivider(Context context, int dividerHight, Drawable dividerDrawable) {
        this(context);
        mDividerHight = dividerHight;
        mDividerDarwable = dividerDrawable;
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state);
        //画水平和垂直分割线
        drawHorizontalDivider(c, parent);
        drawVerticalDivider(c, parent);
    }

    public void drawVerticalDivider(Canvas c, RecyclerView parent) {
        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

            final int top = child.getTop() - params.topMargin;
            final int bottom = child.getBottom() + params.bottomMargin;

            int left = 0;
            int right = 0;

            //左边第一列
            if ((i % 3) == 0) {
                //item左边分割线
                left = child.getLeft();
                right = left + mDividerHight;
                mDividerDarwable.setBounds(left, top, right, bottom);
                mDividerDarwable.draw(c);
                if (mColorPaint != null) {
                    c.drawRect(left, top, right, bottom, mColorPaint);
                }
                //item右边分割线
                left = child.getRight() + params.rightMargin - mDividerHight;
                right = left + mDividerHight;
            } else {
                //非左边第一列
                left = child.getRight() + params.rightMargin - mDividerHight;
                right = left + mDividerHight;
            }
            //画分割线
            mDividerDarwable.setBounds(left, top, right, bottom);
            mDividerDarwable.draw(c);
            if (mColorPaint != null) {
                c.drawRect(left, top, right, bottom, mColorPaint);
            }

        }
    }

    public void drawHorizontalDivider(Canvas c, RecyclerView parent) {

        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

            final int left = child.getLeft() - params.leftMargin - mDividerHight;
            final int right = child.getRight() + params.rightMargin;
            int top = 0;
            int bottom = 0;

            // 最上面一行
            if ((i / 3) == 0) {
                //当前item最上面的分割线
                top = child.getTop();
                //当前item下面的分割线
                bottom = top + mDividerHight;
                mDividerDarwable.setBounds(left, top, right, bottom);
                mDividerDarwable.draw(c);
                if (mColorPaint != null) {
                    c.drawRect(left, top, right, bottom, mColorPaint);
                }
                top = child.getBottom() + params.bottomMargin;
                bottom = top + mDividerHight;
            } else {
                top = child.getBottom() + params.bottomMargin;
                bottom = top + mDividerHight;
            }
            //画分割线
            mDividerDarwable.setBounds(left, top, right, bottom);
            mDividerDarwable.draw(c);
            if (mColorPaint != null) {
                c.drawRect(left, top, right, bottom, mColorPaint);
            }
        }
    }
}

4. Adapter

public class MyRecycleViewAdapter extends RecyclerView.Adapter<MyRecycleViewAdapter.MyViewHolder> {

    private LayoutInflater mLayoutInflater;
    private List<String> mDataList;
    private int mItemLayout;

    public MyRecycleViewAdapter(Context context, int itemLayout, List<String> datalist) {
        mLayoutInflater = LayoutInflater.from(context);
        mItemLayout = itemLayout;
        mDataList = datalist;
    }

    @Override
    public MyRecycleViewAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new MyViewHolder(mLayoutInflater.inflate(mItemLayout, parent, false));
    }

    @Override
    public void onBindViewHolder(MyRecycleViewAdapter.MyViewHolder holder, int position) {
        holder.mTextView.setText(mDataList.get(position));
    }

    @Override
    public int getItemCount() {
        return mDataList.size();
    }


    class MyViewHolder extends RecyclerView.ViewHolder {

        private TextView mTextView;

        public MyViewHolder(View itemView) {
            super(itemView);
            mTextView = (TextView) itemView.findViewById(R.id.tv);
        }
    }
}

adapter 的item布局

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/tv"
        android:gravity="center"
        android:layout_width="match_parent"
        android:layout_height="60dp"/>

</FrameLayout>

未完待续……

评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值