Android RecyclerView网格布局(支持多种分割线)详解(2)
作者:小花猫cat
上篇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>
未完待续……
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。