Android RecyclerView网格布局(支持多种分割线)详解(2)
发布时间 - 2026-01-10 23:16:58 点击率:次上篇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>
未完待续……
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# Android
# RecyclerView
# 网格布局
# RecyclerView底部分割线去除的方法
# android中RecyclerView自定义分割线实现
# 万能RecyclerView分割线
# RecyclerView消除底部分割线的方法
# RecyclerView的万能分割线
# 浅谈Android RecyclerView 间距全适配
# Android RecyclerView使用GridLayoutManager间距设置的方法
# RecyclerView设置间距和添加分割线的方法
# 分割线
# 都有
# 只需
# 的是
# 都是
# 如果你
# 我会
# 上了
# 水平和
# 两种
# 遍历
# 所需
# 要在
# 我们可以
# 很简单
# 它可以
# 不做
# 会说
# 还不错
# 管理器
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
如何为不同团队 ID 动态生成多个非值班状态按钮
javascript中的数组方法有哪些_如何利用数组方法简化数据处理
通义万相免费版怎么用_通义万相免费版使用方法详细指南【教程】
Laravel如何实现本地化和多语言支持_Laravel多语言配置与翻译文件管理
在线制作视频的网站有哪些,电脑如何制作视频短片?
详解免费开源的DotNet二维码操作组件ThoughtWorks.QRCode(.NET组件介绍之四)
如何确保西部建站助手FTP传输的安全性?
Laravel怎么实现观察者模式Observer_Laravel模型事件监听与解耦开发【指南】
laravel怎么使用数据库工厂(Factory)生成带有关联模型的数据_laravel Factory生成关联数据方法
Laravel如何设置定时任务(Cron Job)_Laravel调度器与任务计划配置
Laravel Fortify是什么,和Jetstream有什么关系
实例解析angularjs的filter过滤器
node.js报错:Cannot find module 'ejs'的解决办法
济南网站建设制作公司,室内设计网站一般都有哪些功能?
如何挑选优质建站一级代理提升网站排名?
iOS UIView常见属性方法小结
Gemini手机端怎么发图片_Gemini手机端发图方法【步骤】
HTML5空格和margin有啥区别_空格与外边距的使用场景【说明】
网站优化排名时,需要考虑哪些问题呢?
桂林网站制作公司有哪些,桂林马拉松怎么报名?
零基础网站服务器架设实战:轻量应用与域名解析配置指南
哪家制作企业网站好,开办像阿里巴巴那样的网络公司和网站要怎么做?
Laravel表单请求验证类怎么用_Laravel Form Request分离验证逻辑教程
Laravel如何创建自定义Artisan命令?(代码示例)
使用豆包 AI 辅助进行简单网页 HTML 结构设计
Laravel怎么处理异常_Laravel自定义异常处理与错误页面教程
使用Dockerfile构建java web环境
如何安全更换建站之星模板并保留数据?
Win11怎么设置默认图片查看器_Windows11照片应用关联设置
Laravel怎么集成Vue.js_Laravel Mix配置Vue开发环境
iOS正则表达式验证手机号、邮箱、身份证号等
HTML透明颜色代码怎么让图片透明_给img元素加透明色的技巧【方法】
三星、SK海力士获美批准:可向中国出口芯片制造设备
Python正则表达式进阶教程_复杂匹配与分组替换解析
高性价比服务器租赁——企业级配置与24小时运维服务
Laravel怎么返回JSON格式数据_Laravel API资源Response响应格式化【技巧】
大连网站制作公司哪家好一点,大连买房网站哪个好?
教你用AI润色文章,让你的文字表达更专业
Laravel Telescope怎么调试_使用Laravel Telescope进行应用监控与调试
Laravel如何使用Contracts(契约)进行编程_Laravel契约接口与依赖反转
Python高阶函数应用_函数作为参数说明【指导】
常州企业网站制作公司,全国继续教育网怎么登录?
如何使用 jQuery 正确渲染 Instagram 风格的标签列表
微信小程序 配置文件详细介绍
个人网站制作流程图片大全,个人网站如何注销?
Laravel如何实现多表关联模型定义_Laravel多对多关系及中间表数据存取【方法】
如何在宝塔面板中创建新站点?
如何用5美元大硬盘VPS安全高效搭建个人网站?
怎么用AI帮你设计一套个性化的手机App图标?
php在windows下怎么调试_phpwindows环境调试操作说明【操作】

