当前位置: 首页 > news >正文

自定义RecyclerView的ItemDecoration,用于处理网格布局间距装饰器(支持边缘间距独立控制)

自定义RecyclerView的ItemDecoration,用于处理网格布局的间距,网格布局间距装饰器(支持边缘间距独立控制),为RecyclerView网格布局提供灵活的间距控制,可单独设置各边缘间距。

核心功能说明:

  1. 灵活的边缘控制:可单独设置首列/末列/首行/末行的间距
  2. 智能间距分配:
  • 多列布局时自动将间距平分到相邻item两侧
  • 单列布局时直接应用指定间距

    3.两种边缘模式:

  • includeEdge=true:默认包含顶部/底部边缘间距
  • includeEdge=false:不包含默认边缘间距(可单独设置)

      4.辅助计算功能:提供getTotalWidthNeeded()方法预计算item宽度

如:GridLayoutManager 设计一个一行4列的,且每列的间距都是10dp

// 在Activity或Fragment中
RecyclerView recyclerView = findViewById(R.id.recyclerView);// 设置GridLayoutManager,4列
GridLayoutManager layoutManager = new GridLayoutManager(this, 4);
recyclerView.setLayoutManager(layoutManager);// 设置ItemDecoration来添加间距
int spacingInPixels = getResources().getDimensionPixelSize(R.dimen.grid_spacing);// 移除旧的 ItemDecoration(避免重复添加)if (recyclerView.getItemDecorationCount() > 0) {recyclerView.removeItemDecorationAt(0);}// 添加自定义边距recyclerView.addItemDecoration(new GridSpacingItemDecoration(4,spacingInPixels ,true,spacingInPixels,spacingInPixels,0,spacingInPixels));// 设置适配器
ImageAdapter adapter = new ImageAdapter(imageList); // 假设有适配器
recyclerView.setAdapter(adapter);

GridSpacingItemDecoration.java 代码:

import android.graphics.Rect;
import android.support.v7.widget.RecyclerView;
import android.view.View;/*** 网格布局间距装饰器(支持边缘间距独立控制)* 功能:为RecyclerView网格布局提供灵活的间距控制,可单独设置各边缘间距*/
public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {private final int spanCount;          // 网格列数private final int spacing;            // 默认间距大小(像素)private final boolean includeEdge;    // 是否包含边缘间距(影响顶部/底部默认行为)// 以下参数为可选边缘间距控制(-1表示使用默认间距)private int includeFirstColumnSpacing = -1;   // 第一列左边距(可覆盖默认值)private int includeLastColumnSpacing = -1;    // 最后一列右边距(可覆盖默认值)private int includeFirstRowTopSpacing = -1;   // 第一行上边距(可覆盖默认值)private int includeLastRowBottomSpacing = -1; // 最后一行下边距(可覆盖默认值)/*** 全参数构造函数* * @param spanCount 网格列数(必须大于0)* @param spacing 默认间距值(像素)* @param includeEdge 是否包含边缘间距(影响顶部/底部默认行为)* @param includeFirstColumnSpacing 第一列左边距(-1表示使用默认间距)* @param includeLastColumnSpacing 最后一列右边距(-1表示使用默认间距)* @param includeFirstRowTopSpacing 第一行上边距(-1表示使用默认间距)* @param includeLastRowBottomSpacing 最后一行下边距(-1表示使用默认间距)*/public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge,int includeFirstColumnSpacing,int includeLastColumnSpacing,int includeFirstRowTopSpacing,int includeLastRowBottomSpacing) {this.spanCount = spanCount;this.spacing = spacing;this.includeEdge = includeEdge;this.includeFirstColumnSpacing = includeFirstColumnSpacing;this.includeLastColumnSpacing = includeLastColumnSpacing;this.includeFirstRowTopSpacing = includeFirstRowTopSpacing;this.includeLastRowBottomSpacing = includeLastRowBottomSpacing;}@Overridepublic void getItemOffsets(Rect outRect, View view, RecyclerView parent,RecyclerView.State state) {int position = parent.getChildAdapterPosition(view); // 当前item位置int column = position % spanCount; // 当前item所在列(0~spanCount-1)int totalItemCount = parent.getAdapter().getItemCount(); // 总item数int totalRows = (int) Math.ceil((double) totalItemCount / spanCount); // 计算总行数int currentRow = position / spanCount + 1; // 当前行号(从1开始)/* ========== 1. 处理左右边距 ========== */if (spanCount == 1) {// 单列特殊情况处理outRect.left = getEffectiveSpacing(includeFirstColumnSpacing, spacing);outRect.right = getEffectiveSpacing(includeLastColumnSpacing, spacing);} else {// 多列常规处理if (column == 0) {// 第一列:左间距可定制,右间距为默认一半outRect.left = getEffectiveSpacing(includeFirstColumnSpacing, spacing);outRect.right = spacing / 2;} else if (column == spanCount - 1) {// 最后一列:左间距为默认一半,右间距可定制outRect.left = spacing / 2;outRect.right = getEffectiveSpacing(includeLastColumnSpacing, spacing);} else {// 中间列:左右间距均为默认一半(实现等间距分布)outRect.left = spacing / 2;outRect.right = spacing / 2;}}/* ========== 2. 处理上下边距 ========== */if (includeEdge) {// 包含边缘模式if (currentRow == 1) {// 第一行顶部间距outRect.top = getEffectiveSpacing(includeFirstRowTopSpacing, spacing);}// 底部间距处理if (currentRow == totalRows) {// 最后一行底部间距可定制outRect.bottom = getEffectiveSpacing(includeLastRowBottomSpacing, spacing);} else if (currentRow < totalRows) {// 中间行固定底部间距outRect.bottom = spacing;}} else {// 不包含边缘模式outRect.top = currentRow == 1 ? getEffectiveSpacing(includeFirstRowTopSpacing, spacing) : spacing;// 最后一行特殊处理if (currentRow == totalRows) {outRect.bottom = getEffectiveSpacing(includeLastRowBottomSpacing, spacing);}}}/*** 获取有效间距值* @param customSpacing 自定义间距值(-1表示使用默认值)* @param defaultSpacing 默认间距值* @return 实际使用的间距值*/private int getEffectiveSpacing(int customSpacing, int defaultSpacing) {return customSpacing > -1 ? customSpacing : defaultSpacing;}/*** 计算RecyclerView需要的总宽度(用于预计算item宽度)* @param screenWidth 屏幕可用宽度* @return 单个item的理论宽度*/public int getTotalWidthNeeded(int screenWidth) {if (spanCount == 0) return screenWidth;// 计算总间距 = 列间间距 + 边缘间距int totalSpacing = (spanCount > 1) ? (spanCount - 1) * spacing : 0;if (includeFirstColumnSpacing > 0) totalSpacing += spacing;if (includeLastColumnSpacing > 0) totalSpacing += spacing;// 返回单个item宽度 = (总宽度 - 总间距) / 列数return (screenWidth - totalSpacing) / spanCount;}
}

http://www.dtcms.com/a/269735.html

相关文章:

  • ubuntu vscode 点击变量链接进去后 怎么返回原来的位置
  • LocalStorage和SessionStorage的区别和应用
  • 马尔可夫决策过程
  • python办公自动化----使用pandas和os合并多个订单表
  • 【python】 `parse_time_to_seconds` 在功能及健壮性上有以下主要区别
  • ​扣子Coze飞书多维表插件添加数据记录
  • 【UE5】虚幻引擎小百科
  • std::function
  • coze平台AI Agent开发入门之工作流的基本使用方法
  • Redis 缓存机制 及问题场景 及解决方案
  • 接口自动化工具-SoapUI
  • kotlin
  • Ubuntu22.04下微星B850M主板 无wifi模块
  • AR 双缝干涉实验亮相:创新科技实验范式,开拓 AR 技术新局​
  • 传输层协议TCP、UDP
  • SpringBoot+Mybatis+MySQL+Vue+ElementUI前后端分离版:整体布局、架构调整(二)
  • 基于FPGA的累加算法实现
  • 2. 两数相加
  • 从零实现一个GPT 【React + Express】--- 【1】初始化前后端项目,实现模型接入+SSE
  • 领域驱动设计(DDD)重塑金融系统架构
  • Qt 与Halcon联合开发九:算法类设计与实现讲解(附源码)
  • AlphaEvolve:谷歌的算法进化引擎 | 从数学证明到芯片设计的AI自主发现新纪元
  • 告别“电量焦虑”,BLE如何提升可穿戴设备续航能力?
  • Flutter基础(前端教程④-组件拼接)
  • Linux NUMA调优实战:多线程程序加速方法
  • 电路研究9.3.10——合宙Air780EP中的AT开发指南:阿里云应用指南
  • Deepoc大模型:重构无人机认知边界的具身智能革命
  • 华为泰山服务器重启后出现 XFS 文件系统磁盘“不识别”(无法挂载或访问),但挂载点目录仍在且无数据
  • WPA2 与 WPA3:深入解析Wi-Fi安全协议
  • Linux网络:UDP socket创建流程与简单通信