网格吸顶分割线,网格分割线,列表分割线

网格分割线:

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;
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值