网格分割线:
package com.yzyz.im.adapater;
import android.graphics.Rect;
import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
/**
* Description:
* <p>
* Author: [luochengkai]
* Date: 2023-06-06 周二 11:39
* Version: 1.0
* Updater:
* Update Time:
*/
public class ImGridSpaceItemDecoration extends RecyclerView.ItemDecoration {
/**
* 每行个数
*/
private int mSpanCount;
/**
* 间距
*/
private int mSpacing;
/**
* 顶部间距
*/
private int mTopSpace;
/**
* 底部间距
*/
private int mBottomSpace;
/**
* 中间间距
*/
private int mCenterSpacing;
/**
* 中间是否跟两边大小不一致
*/
private boolean mCenterEdge;
/**
* 距屏幕周围是否也有间距
*/
private boolean mIncludeEdge;
/**
* 头部 不显示间距的item个数
*/
private int mStartFromSize;
/**
* 尾部 不显示间距的item个数 默认不处理最后一个item的间距
*/
private int mEndFromSize = 0;
/**
* 瀑布流 头部第一个整行的position
*/
private int fullPosition = -1;
public ImGridSpaceItemDecoration(int spacing) {
this(spacing, true);
}
/**
* @param spacing item 间距
* @param includeEdge item 距屏幕周围是否也有间距
*/
public ImGridSpaceItemDecoration(int spacing, boolean includeEdge) {
this.mSpacing = spacing;
this.mTopSpace = spacing;
this.mBottomSpace = spacing;
this.mIncludeEdge = includeEdge;
}
/**
* @param leftSpace item 间距
* @param includeEdge item 距屏幕周围是否也有间距
*/
public ImGridSpaceItemDecoration(int leftSpace, int topSpace, int bottomSpace, int centerSpace, boolean includeEdge) {
this.mSpacing = leftSpace;
this.mTopSpace = topSpace;
this.mBottomSpace = bottomSpace;
this.mCenterSpacing = centerSpace;
this.mIncludeEdge = includeEdge;
this.mCenterEdge = true;
}
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
int lastPosition = state.getItemCount() - 1;
int position = parent.getChildAdapterPosition(view);
if (mStartFromSize <= position && position <= lastPosition - mEndFromSize) {
// 行
int spanGroupIndex = -1;
// 列
int column = 0;
// 瀑布流是否占满一行
boolean fullSpan = false;
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
GridLayoutManager.SpanSizeLookup spanSizeLookup = gridLayoutManager.getSpanSizeLookup();
int spanCount = gridLayoutManager.getSpanCount();
// 当前position的spanSize
int spanSize = spanSizeLookup.getSpanSize(position);
// 一行几个
mSpanCount = spanCount / spanSize;
// =0 表示是最左边 0 2 4
int spanIndex = spanSizeLookup.getSpanIndex(position, spanCount);
// 列
column = spanIndex / spanSize;
// 行 减去mStartFromSize,得到从0开始的行
spanGroupIndex = spanSizeLookup.getSpanGroupIndex(position, spanCount) - mStartFromSize;
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
// 瀑布流获取列方式不一样
StaggeredGridLayoutManager.LayoutParams params = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams();
// 列
column = params.getSpanIndex();
// 是否是全一行
fullSpan = params.isFullSpan();
mSpanCount = ((StaggeredGridLayoutManager) layoutManager).getSpanCount();
}
// 减掉不设置间距的position,得到从0开始的position
position = position - mStartFromSize;
Log.e(ImGridSpaceItemDecoration.class.getSimpleName(), "lastPosition:" + lastPosition + "----position:" + position + "-----column:" + column);
if (mIncludeEdge) {
/*
*示例:
* spacing = 10 ;spanCount = 3
* ---------10--------
* 10 3+7 6+4 10
* ---------10--------
* 10 3+7 6+4 10
* ---------10--------
*/
if (fullSpan) {
outRect.left = 0;
outRect.right = 0;
} else {
if (mCenterEdge) {
if (column % mSpanCount == 0) {
outRect.left = mSpacing;
outRect.right = mCenterSpacing / 2;
} else if (column % mSpanCount == mSpanCount - 1) {
outRect.left = mCenterSpacing / 2;
outRect.right = mSpacing;
} else {
outRect.left = mCenterSpacing / 2;
outRect.right = mCenterSpacing / 2;
}
} else {
outRect.left = mSpacing - column * mSpacing / mSpanCount;
outRect.right = (column + 1) * mSpacing / mSpanCount;
}
}
if (spanGroupIndex > -1) {
// grid 显示规则
if (spanGroupIndex < 1 && position < mSpanCount) {
// 第一行才有上间距
outRect.top = mTopSpace;
}
} else {
if (fullPosition == -1 && position < mSpanCount && fullSpan) {
// 找到头部第一个整行的position,后面的上间距都不显示
fullPosition = position;
}
// Stagger显示规则 头部没有整行或者头部体验整行但是在之前的position显示上间距
boolean isFirstLineStagger = (fullPosition == -1 || position < fullPosition) && (position < mSpanCount);
if (isFirstLineStagger) {
// 第一行才有上间距
outRect.top = mTopSpace;
}
}
outRect.bottom = mBottomSpace;
} else {
/*
*示例:
* spacing = 10 ;spanCount = 3
* --------0--------
* 0 3+7 6+4 0
* -------10--------
* 0 3+7 6+4 0
* --------0--------
*/
if (fullSpan) {
outRect.left = 0;
outRect.right = 0;
} else {
outRect.left = column * mSpacing / mSpanCount;
outRect.right = mSpacing - (column + 1) * mSpacing / mSpanCount;
}
if (spanGroupIndex > -1) {
if (spanGroupIndex >= 1) {
// 超过第0行都显示上间距
outRect.top = mTopSpace;
}
} else {
if (fullPosition == -1 && position < mSpanCount && fullSpan) {
// 找到头部第一个整行的position
fullPosition = position;
}
// Stagger上间距显示规则
boolean isStaggerShowTop = position >= mSpanCount || (fullSpan && position != 0) || (fullPosition != -1 && position != 0);
if (isStaggerShowTop) {
// 超过第0行都显示上间距
outRect.top = mTopSpace;
}
}
}
}
}
/**
* 设置从哪个位置 开始设置间距
*
* @param startFromSize 一般为HeaderView的个数 + 刷新布局(不一定设置)
*/
public ImGridSpaceItemDecoration setStartFrom(int startFromSize) {
this.mStartFromSize = startFromSize;
return this;
}
/**
* 设置从哪个位置 结束设置间距。默认为1,默认用户设置了上拉加载
*
* @param endFromSize 一般为FooterView的个数 + 加载更多布局(不一定设置)
*/
public ImGridSpaceItemDecoration setEndFromSize(int endFromSize) {
this.mEndFromSize = endFromSize;
return this;
}
/**
* 设置从哪个位置 结束设置间距
*
* @param startFromSize 一般为HeaderView的个数 + 刷新布局(不一定设置)
* @param endFromSize 默认为1,一般为FooterView的个数 + 加载更多布局(不一定设置)
*/
public ImGridSpaceItemDecoration setNoShowSpace(int startFromSize, int endFromSize) {
this.mStartFromSize = startFromSize;
this.mEndFromSize = endFromSize;
return this;
}
}
垂直分割线
package com.yzyz.im.adapater;
import android.graphics.Rect;
import android.view.View;
import androidx.recyclerview.widget.RecyclerView;
/**
* Description:
* Author: zhuwanting
* Date: 2023-07-26 周三 10:22
*/
public class ImItemSpacingDecoration extends RecyclerView.ItemDecoration {
private int spacing; // 间距大小
public ImItemSpacingDecoration(int spacing) {
this.spacing = spacing;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
// 如果不是第一个Item,设置顶部间距
if (parent.getChildAdapterPosition(view) == 0) {
outRect.left = spacing;
}
}
}
网格分割线带吸顶
package com.example.itemdecoration;
import android.annotation.SuppressLint;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/*
* @author json_qiu
* @emil json_qiu@hotmail.com
* create at
* description:
*/
public class StickyItemDecoration extends RecyclerView.ItemDecoration {
@ColorInt
private int mGroupTextColor = Color.WHITE;//字体颜色,默认黑色
private int mSideMargin = 10; //边距 左边距
private int mTextSize = 50; //字体大小
private TextPaint mTextPaint;
private Paint mGroutPaint;
/**
* group背景色,默认透明
*/
@ColorInt
int mGroupBackground = Color.parseColor("#48BDFF");
/**
* 悬浮栏高度
*/
int mGroupHeight = 120;
/**
* 间距
*/
int mSpacing = 0;
/**
* 顶部间距
*/
private int mTopSpace;
/**
* 底部间距
*/
private int mBottomSpace;
/**
* 中间间距
*/
private int mCenterSpacing;
/**
* 中间是否跟两边大小不一致
*/
private boolean mCenterEdge = false;
/**
* 距屏幕周围是否也有间距
*/
private boolean mIncludeEdge = true;
/**
* RecyclerView头部数量
* 最小为0
*/
int mHeaderCount;
/**
* 尾部 不显示间距的item个数 默认不处理最后一个item的间距
*/
private int mEndCount = 0;
/**
* 瀑布流 头部第一个整行的position
*/
private int fullPosition = -1;
protected ImSkickyDecorationCallback mImSkickyDecorationCallback;
protected boolean mSticky = true;
private void initGroupTitlePaint() {
mGroutPaint = new Paint();
mGroutPaint.setColor(mGroupBackground);
//设置悬浮栏中文本的画笔
mTextPaint = new TextPaint();
mTextPaint.setAntiAlias(true);
mTextPaint.setTextSize(mTextSize);
mTextPaint.setColor(mGroupTextColor);
mTextPaint.setTextAlign(Paint.Align.LEFT);
}
public void setSpacing(int mSpacing) {
this.mSpacing = mSpacing;
this.mTopSpace = mSpacing;
}
public StickyItemDecoration(ImSkickyDecorationCallback mImSkickyDecorationCallback) {
this.mImSkickyDecorationCallback = mImSkickyDecorationCallback;
initGroupTitlePaint();
}
/**
* 获取真实的position
*
* @param position
* @return
*/
protected int getRealPosition(int position) {
return position - mHeaderCount;
}
@SuppressLint("ClickableViewAccessibility")
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDrawOver(c, parent, state);
//点击事件处理
if (gestureDetector == null) {
gestureDetector = new GestureDetector(parent.getContext(), gestureListener);
parent.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
});
}
stickyHeaderPosArray.clear();
final int itemCount = state.getItemCount();
final int childCount = parent.getChildCount();
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
for (int i = 0; i < childCount; i++) {
View childView = parent.getChildAt(i);
int position = parent.getChildAdapterPosition(childView);
int realPosition = getRealPosition(position);
if (isFirstInGroup(realPosition) || isFirstInRecyclerView(realPosition, i)) {
//绘制悬浮
int bottom = !mSticky ? childView.getTop() : Math.max(mGroupHeight, (childView.getTop() + parent.getPaddingTop()));//决定当前顶部第一个悬浮Group的bottom
if (mSticky && position + 1 < itemCount) {
//下一组的第一个View接近头部
int viewBottom = childView.getBottom();
if (isLastLineInGroup(parent, realPosition) && viewBottom < bottom) {
bottom = viewBottom;
}
}
drawDecoration(c, realPosition, left, right, bottom);
if (mImSkickyDecorationCallback != null) {
stickyHeaderPosArray.put(realPosition, new ClickInfo(bottom));
}
}
}
}
/**
* 绘制悬浮框
*
* @param c
* @param realPosition
* @param left
* @param right
* @param bottom
*/
private void drawDecoration(Canvas c, int realPosition, int left, int right, int bottom) {
String curGroupName; //当前item对应的Group
int firstPositionInGroup = getFirstInGroupWithCash(realPosition);
curGroupName = getGroupTitle(firstPositionInGroup);
//根据top绘制group背景
c.drawRect(left, bottom - mGroupHeight, right, bottom, mGroutPaint);
if (curGroupName == null) {
return;
}
Paint.FontMetrics fm = mTextPaint.getFontMetrics();
//文字竖直居中显示
float baseLine = bottom - (mGroupHeight - (fm.bottom - fm.top)) / 2 - fm.bottom;
//获取文字宽度
mSideMargin = Math.abs(mSideMargin);
c.drawText(curGroupName, left + mSideMargin, baseLine, mTextPaint);
}
/**
* 获取组名
*
* @param realPosition realPosition
* @return 组名
*/
String getGroupTitle(int realPosition) {
if (mImSkickyDecorationCallback != null) {
return mImSkickyDecorationCallback.getGroupTitle(realPosition);
} else {
return null;
}
}
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
int position = parent.getChildAdapterPosition(view);
int lastPosition = state.getItemCount() - 1;
int realPosition = getRealPosition(position);
if (mHeaderCount <= position && position <= lastPosition - mEndCount) {
int mSpanCount = 0;
// 列
int column = 0;
// 瀑布流是否占满一行
boolean fullSpan = false;
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
GridLayoutManager.SpanSizeLookup spanSizeLookup = gridLayoutManager.getSpanSizeLookup();
int spanCount = gridLayoutManager.getSpanCount();
// 当前position的spanSize
int spanSize = spanSizeLookup.getSpanSize(position);
// 一行几个
mSpanCount = spanCount / spanSize;
// =0 表示是最左边 0 2 4
int spanIndex = spanSizeLookup.getSpanIndex(position, spanCount);
// 列
column = spanIndex / spanSize;
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
// 瀑布流获取列方式不一样
StaggeredGridLayoutManager.LayoutParams params = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams();
// 列
column = params.getSpanIndex();
// 是否是全一行
fullSpan = params.isFullSpan();
mSpanCount = ((StaggeredGridLayoutManager) layoutManager).getSpanCount();
}
if (mIncludeEdge) {
if (fullSpan) {
outRect.left = 0;
outRect.right = 0;
} else {
if (mCenterEdge) {
if (column % mSpanCount == 0) {
outRect.left = mSpacing;
outRect.right = mCenterSpacing / 2;
} else if (column % mSpanCount == mSpanCount - 1) {
outRect.left = mCenterSpacing / 2;
outRect.right = mSpacing;
} else {
outRect.left = mCenterSpacing / 2;
outRect.right = mCenterSpacing / 2;
}
} else {
outRect.left = mSpacing - column * mSpacing / mSpanCount;
outRect.right = (column + 1) * mSpacing / mSpanCount;
}
}
outRect.bottom = mBottomSpace;
} else {
/*
*示例:
* spacing = 10 ;spanCount = 3
* --------0--------
* 0 3+7 6+4 0
* -------10--------
* 0 3+7 6+4 0
* --------0--------
*/
if (fullSpan) {
outRect.left = 0;
outRect.right = 0;
} else {
outRect.left = column * mSpacing / mSpanCount;
outRect.right = mSpacing - (column + 1) * mSpacing / mSpanCount;
}
}
}
RecyclerView.LayoutManager manager = parent.getLayoutManager();
if (manager instanceof GridLayoutManager) {
//网格布局
int spanCount = ((GridLayoutManager) manager).getSpanCount();
if (!isHeader(realPosition)) {
if (isFirstLineInGroup(realPosition, spanCount)) {
//为悬浮view预留空间
outRect.top = mGroupHeight;
} else {
//为分割线预留空间
outRect.top = mTopSpace;
}
}
} else {
//其他的默认为线性布局
//只有是同一组的第一个才显示悬浮栏
if (!isHeader(realPosition)) {
if (isFirstInGroup(realPosition)) {
//为悬浮view预留空间
outRect.top = mGroupHeight;
} else {
//为分割线预留空间
outRect.top = mTopSpace;
}
}
}
}
/**
* 判断是不是组中的第一个位置
* 根据前一个组名,判断当前是否为新的组
* 当前为groupId为null时,则与上一个为同一组
*/
protected boolean isFirstInGroup(int realPosition) {
if (realPosition < 0) {
//小于header数量,不是第一个
return false;
} else if (realPosition == 0) {
//等于header数量,为第一个
return true;
}
String preGroupId;
if (realPosition <= 0) {
preGroupId = null;
} else {
preGroupId = getGroupTitle(realPosition - 1);
}
String curGroupId = getGroupTitle(realPosition);
if (curGroupId == null) {
return false;
}
return !TextUtils.equals(preGroupId, curGroupId);
}
/**
* 是否在RecyclerView处于第一个(header部分不算)
*
* @param realPosition 总的position
* @param index RecyclerView中的Index
* @return
*/
protected boolean isFirstInRecyclerView(int realPosition, int index) {
return realPosition >= 0 && index == 0;
}
/**
* 是否为Header
*/
protected boolean isHeader(int realPosition) {
return realPosition < 0;
}
/**
* 判断是不是新组的第一行(GridLayoutManager使用)
* 利用当前行的第一个对比前一个组名,判断当前是否为新组的第一样
*/
protected boolean isFirstLineInGroup(int realPosition, int spanCount) {
if (realPosition < 0) {
//小于header数量,不是第一个
return false;
} else if (realPosition == 0) {
return true;
} else {
int posFirstInGroup = getFirstInGroupWithCash(realPosition);
if (realPosition - posFirstInGroup < spanCount) {
return true;
} else {
return false;
}
}
}
/**
* 网格布局需要调用
*
* @param recyclerView recyclerView
* @param gridLayoutManager gridLayoutManager
*/
public void resetSpan(RecyclerView recyclerView, GridLayoutManager gridLayoutManager) {
if (recyclerView == null) {
throw new NullPointerException("recyclerView not allow null");
}
if (gridLayoutManager == null) {
throw new NullPointerException("gridLayoutManager not allow null");
}
final int spanCount = gridLayoutManager.getSpanCount();
//相当于weight
GridLayoutManager.SpanSizeLookup lookup = new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
int span;
int realPosition = getRealPosition(position);
if (realPosition < 0) {
//小于header数量
span = spanCount;
} else {
String curGroupId = getGroupTitle(realPosition);
String nextGroupId;
try {
//防止外面没判断,导致越界
nextGroupId = getGroupTitle(realPosition + 1);
} catch (Exception e) {
nextGroupId = curGroupId;
}
if (!TextUtils.equals(curGroupId, nextGroupId)) {
//为本行的最后一个
int posFirstInGroup = getFirstInGroupWithCash(realPosition);
span = spanCount - (realPosition - posFirstInGroup) % spanCount;
} else {
span = 1;
}
}
return span;
}
};
gridLayoutManager.setSpanSizeLookup(lookup);
}
/**
* down事件在顶部悬浮栏中
*/
private boolean mDownInHeader;
/**
* RecyclerView onInterceptEvent中down事件调用,用于处理点击穿透问题
*
* @param event
*/
public void onEventDown(MotionEvent event) {
if (event == null) {
mDownInHeader = false;
return;
}
mDownInHeader = event.getY() > 0 && event.getY() < mGroupHeight;
}
/**
* RecyclerView onInterceptEvent中up事件调用,用于处理点击穿透问题
*
* @param event
* @return
*/
public boolean onEventUp(MotionEvent event) {
if (mDownInHeader) {
float y = event.getY();
boolean isInHeader = y > 0 && y < mGroupHeight;
if (isInHeader) {
return onTouchEvent(event);
}
}
return false;
}
/**
* 得到当前分组第一个item的position
*
* @param realPosition realPosition
*/
protected int getFirstInGroupWithCash(int realPosition) {
return getFirstInGroup(realPosition);
}
/**
* 得到当前分组第一个item的position
*
* @param realPosition realPosition
*/
private int getFirstInGroup(int realPosition) {
if (realPosition <= 0) {
return 0;
} else {
if (isFirstInGroup(realPosition)) {
return realPosition;
} else {
return getFirstInGroup(realPosition - 1);
}
}
}
/**
* 判断自己是否为group的最后一行
*
* @param recyclerView recyclerView
* @param realPosition realPosition
* @return
*/
protected boolean isLastLineInGroup(RecyclerView recyclerView, int realPosition) {
if (realPosition < 0) {
return true;
} else {
String curGroupName = getGroupTitle(realPosition);
String nextGroupName;
RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
//默认往下查找的数量
int findCount = 1;
if (manager instanceof GridLayoutManager) {
int spanCount = ((GridLayoutManager) manager).getSpanCount();
int firstPositionInGroup = getFirstInGroupWithCash(realPosition);
findCount = spanCount - (realPosition - firstPositionInGroup) % spanCount;
}
try {
nextGroupName = getGroupTitle(realPosition + findCount);
} catch (Exception e) {
nextGroupName = curGroupName;
}
if (nextGroupName == null) {
return true;
}
return !TextUtils.equals(curGroupName, nextGroupName);
}
}
/**
* 点击事件调用
*
* @param realPosition realPosition
*/
private void onGroupClick(int realPosition, int viewId) {
if (mImSkickyDecorationCallback != null) {
mImSkickyDecorationCallback.onGroupTitleClick(realPosition);
}
}
/**
* 记录每个头部和悬浮头部的坐标信息【用于点击事件】
* 位置由子类添加
*/
protected HashMap<Integer, ClickInfo> stickyHeaderPosArray = new HashMap<>();
private GestureDetector gestureDetector;
private GestureDetector.OnGestureListener gestureListener = new GestureDetector.OnGestureListener() {
@Override
public boolean onDown(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return onTouchEvent(e);
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return false;
}
};
/**
* 对touch事件处理,找到点击事件
*
* @param e
* @return
*/
private boolean onTouchEvent(MotionEvent e) {
for (Map.Entry<Integer, ClickInfo> entry : stickyHeaderPosArray.entrySet()) {
ClickInfo value = stickyHeaderPosArray.get(entry.getKey());
float y = e.getY();
float x = e.getX();
if (value.mBottom - mGroupHeight <= y && y <= value.mBottom) {
//如果点击到分组头
if (value.mDetailInfoList == null || value.mDetailInfoList.size() == 0) {
//没有子View的点击事件
onGroupClick(entry.getKey(), value.mGroupId);
} else {
List<ClickInfo.DetailInfo> list = value.mDetailInfoList;
boolean isChildViewClicked = false;
for (ClickInfo.DetailInfo detailInfo : list) {
if (detailInfo.top <= y && y <= detailInfo.bottom
&& detailInfo.left <= x && detailInfo.right >= x) {
//当前view被点击
onGroupClick(entry.getKey(), detailInfo.id);
isChildViewClicked = true;
break;
}
}
if (!isChildViewClicked) {
//点击范围不在带有id的子view中,则表示整个groupView被点击
onGroupClick(entry.getKey(), value.mGroupId);
}
}
return true;
}
}
return false;
}
protected void log(String content) {
if (false) {
Log.i("StickDecoration", content);
}
}
public static class ClickInfo {
public int mBottom;
public int mGroupId = View.NO_ID;
/**
* 详细信息
* 对应的子view坐标信息
*/
public List<DetailInfo> mDetailInfoList;
public ClickInfo(int bottom) {
this.mBottom = bottom;
}
public ClickInfo(int bottom, List<DetailInfo> detailInfoList) {
mBottom = bottom;
mDetailInfoList = detailInfoList;
}
public static class DetailInfo {
public int id;
public int left;
public int right;
public int top;
public int bottom;
public DetailInfo(int id, int left, int right, int top, int bottom) {
this.id = id;
this.left = left;
this.right = right;
this.top = top;
this.bottom = bottom;
}
}
}
public static interface ImSkickyDecorationCallback {
/***
* 获取指定位置的title
* @param position
* @return
*/
String getGroupTitle(int position);
/***
* 点击了指定位置的title
* @param position
* @return
*/
void onGroupTitleClick(int position);
}
public static class Builder {
private StickyItemDecoration mDecoration;
private Builder(ImSkickyDecorationCallback mImSkickyDecorationCallback) {
mDecoration = new StickyItemDecoration(mImSkickyDecorationCallback);
}
public static Builder init(ImSkickyDecorationCallback mImSkickyDecorationCallback) {
return new Builder(mImSkickyDecorationCallback);
}
/**
* 设置Group背景
*
* @param background 背景色
*/
public Builder setGroupBackground(@ColorInt int background) {
mDecoration.mGroupBackground = background;
mDecoration.mGroutPaint.setColor(mDecoration.mGroupBackground);
return this;
}
/**
* 设置字体大小
*
* @param textSize 字体大小
*/
public Builder setGroupTextSize(int textSize) {
mDecoration.mTextSize = textSize;
mDecoration.mTextPaint.setTextSize(mDecoration.mTextSize);
return this;
}
/**
* 设置Group高度
*
* @param groutHeight 高度
* @return this
*/
public Builder setGroupHeight(int groutHeight) {
mDecoration.mGroupHeight = groutHeight;
return this;
}
/**
* 组TextColor
*
* @param color 颜色
* @return this
*/
public Builder setGroupTextColor(@ColorInt int color) {
mDecoration.mGroupTextColor = color;
mDecoration.mTextPaint.setColor(mDecoration.mGroupTextColor);
return this;
}
/**
* 设置边距
* 靠左时为左边距 靠右时为右边距
*
* @param leftMargin 左右距离
* @return this
*/
public Builder setTextSideMargin(int leftMargin) {
mDecoration.mSideMargin = leftMargin;
return this;
}
/**
* 设置间距
*
* @param mSpacing 间距
* @return this
*/
public Builder setSpacing(int mSpacing) {
mDecoration.setSpacing(mSpacing);
return this;
}
/**
* 重置span
*
* @param recyclerView recyclerView
* @param gridLayoutManager gridLayoutManager
* @return this
*/
public Builder resetSpan(RecyclerView recyclerView, GridLayoutManager gridLayoutManager) {
mDecoration.resetSpan(recyclerView, gridLayoutManager);
return this;
}
/**
* 设置头部数量
* 用于顶部Header不需要设置悬浮的情况(仅LinearLayoutManager)
*
* @param headerCount
* @return
*/
public Builder setHeaderCount(int headerCount) {
if (headerCount >= 0) {
mDecoration.mHeaderCount = headerCount;
}
return this;
}
/**
* 设置是否需要悬浮
*
* @param sticky
* @return
*/
public Builder setSticky(boolean sticky) {
mDecoration.mSticky = sticky;
return this;
}
/**
* 设置是顶部间距
*
* @param mTopSpace
* @return
*/
public Builder setTopSpace(int mTopSpace) {
mDecoration.mTopSpace = mTopSpace;
return this;
}
/**
* 设置底部间距
*
* @param mBottomSpace
* @return
*/
public Builder setBottomSpace(int mBottomSpace) {
mDecoration.mBottomSpace = mBottomSpace;
return this;
}
/**
* 设置中间间距
*
* @param mCenterSpacing
* @return
*/
public Builder setCenterSpacing(int mCenterSpacing) {
mDecoration.mCenterSpacing = mCenterSpacing;
return this;
}
/**
* 设置距屏幕周围是否也有间距
*
* @param mCenterEdge
* @return
*/
public Builder setCenterEdge(boolean mCenterEdge) {
mDecoration.mCenterEdge = mCenterEdge;
return this;
}
/**
* 设置中间是否跟两边大小不一致
*
* @param mIncludeEdge
* @return
*/
public Builder setIncludeEdge(boolean mIncludeEdge) {
mDecoration.mIncludeEdge = mIncludeEdge;
return this;
}
/**
* 设置瀑布流 头部第一个整行的position
*
* @param fullPosition
* @return
*/
public Builder setFullPosition(int fullPosition) {
mDecoration.fullPosition = fullPosition;
return this;
}
public StickyItemDecoration build() {
return mDecoration;
}
}
}