【Android -- UI 开发】RecyclerView 实现顶部悬浮效果

本文介绍了 Android RecyclerView 悬浮效果,具体如下:
在这里插入图片描述

实现思路:

  1. 利用RecyclerView.ItemDecoration绘制Province(就像绘制分割线一样)
  2. 同一组的City,只绘制一个Province
  3. 计算偏移,将当前Province固定在顶部
  4. 根据列表滑动,实现偏移效果

实现

1. 定义一个接口,根据 position 通过接口方法 getGroupName 获取当前省名(由Activity实现)

public interface GroupListener {
    String getGroupName(int position);
}

2. 创建 BaseDecoration 继承 RecyclerView.ItemDecoration

public abstract class BaseDecoration extends RecyclerView.ItemDecoration {
    /**
     * group背景色,默认透明
     */
    @ColorInt
    int mGroupBackground = Color.parseColor("#48BDFF");
    /**
     * 悬浮栏高度
     */
    int mGroupHeight = 120;
    /**
     * 分割线颜色,默认灰色
     */
    @ColorInt
    int mDivideColor = Color.parseColor("#CCCCCC");
    /**
     * 分割线宽度
     */
    int mDivideHeight = 0;

    /**
     * RecyclerView头部数量
     * 最小为0
     */
    int mHeaderCount;

    Paint mDividePaint;
    /**
     * 缓存分组第一个item的position
     */
    private SparseIntArray firstInGroupCash = new SparseIntArray(100);

    protected OnGroupClickListener mOnGroupClickListener;

    protected boolean mSticky = true;

    public BaseDecoration() {
        mDividePaint = new Paint();
        mDividePaint.setColor(mDivideColor);
    }

    /**
     * 设置点击事件
     *
     * @param listener
     */
    protected void setOnGroupClickListener(OnGroupClickListener listener) {
        this.mOnGroupClickListener = listener;
    }

    /**
     * 获取分组名
     *
     * @param realPosition realPosition
     * @return group
     */
    abstract String getGroupName(int realPosition);

    /**
     * 获取真实的position
     * @param position
     * @return
     */
    protected int getRealPosition(int position) {
        return position - mHeaderCount;
    }

    @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 realPosition = getRealPosition(position);
        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 = mDivideHeight;
                }
            }
        } else {
            //其他的默认为线性布局
            //只有是同一组的第一个才显示悬浮栏
            if (!isHeader(realPosition)) {
                if (isFirstInGroup(realPosition)) {
                    //为悬浮view预留空间
                    outRect.top = mGroupHeight;
                } else {
                    //为分割线预留空间
                    outRect.top = mDivideHeight;
                }
            }
        }
    }

    /**
     * 判断是不是组中的第一个位置
     * 根据前一个组名,判断当前是否为新的组
     * 当前为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 = getGroupName(realPosition - 1);
        }
        String curGroupId = getGroupName(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 = getGroupName(realPosition);
                    String nextGroupId;
                    try {
                        //防止外面没判断,导致越界
                        nextGroupId = getGroupName(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 = getGroupName(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 = getGroupName(realPosition + findCount);
            } catch (Exception e) {
                nextGroupName = curGroupName;
            }
            if (nextGroupName == null) {
                return true;
            }
            return !TextUtils.equals(curGroupName, nextGroupName);
        }
    }

    @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();
    }

    /**
     * 点击事件调用
     *
     * @param realPosition realPosition
     */
    private void onGroupClick(int realPosition, int viewId) {
        if (mOnGroupClickListener != null) {
            mOnGroupClickListener.onClick(realPosition, viewId);
        }
    }

    /**
     * 记录每个头部和悬浮头部的坐标信息【用于点击事件】
     * 位置由子类添加
     */
    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;
    }

    /**
     * 绘制分割线
     *
     * @param c
     * @param parent
     * @param childView
     * @param realPosition
     * @param left
     * @param right
     */
    protected void drawDivide(Canvas c, RecyclerView parent, View childView, int realPosition, int left, int right) {
        if (mDivideHeight != 0 && !isHeader(realPosition)) {
            RecyclerView.LayoutManager manager = parent.getLayoutManager();
            if (manager instanceof GridLayoutManager) {
                int spanCount = ((GridLayoutManager) manager).getSpanCount();
                if (!isFirstLineInGroup(realPosition, spanCount)) {
                    float bottom = childView.getTop() + parent.getPaddingTop();
                    //高度小于顶部悬浮栏时,跳过绘制
                    if (bottom >= mGroupHeight) {
                        c.drawRect(left, bottom - mDivideHeight, right, bottom, mDividePaint);
                    }
                }
            } else {
                float bottom = childView.getTop();
                //高度小于顶部悬浮栏时,跳过绘制
                if (bottom >= mGroupHeight) {
                    c.drawRect(left, bottom - mDivideHeight, right, bottom, mDividePaint);
                }
            }
        }
    }

    protected void log(String content) {
        if (false) {
            Log.i("StickDecoration", content);
        }
    }
}

3. StickyDecoration.java

public class StickyDecoration extends BaseDecoration {
    @ColorInt
    private int mGroupTextColor = Color.WHITE;//字体颜色,默认黑色
    private int mSideMargin = 10;   //边距 左边距
    private int mTextSize = 50;     //字体大小
    private GroupListener mGroupListener;

    private TextPaint mTextPaint;
    private Paint mGroutPaint;

    private StickyDecoration(GroupListener groupListener) {
        super();
        this.mGroupListener = groupListener;
        //设置悬浮栏的画笔---mGroutPaint
        mGroutPaint = new Paint();
        mGroutPaint.setColor(mGroupBackground);
        //设置悬浮栏中文本的画笔
        mTextPaint = new TextPaint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setTextSize(mTextSize);
        mTextPaint.setColor(mGroupTextColor);
        mTextPaint.setTextAlign(Paint.Align.LEFT);
    }

    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDrawOver(c, parent, state);
        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 (mOnGroupClickListener != null) {
                    stickyHeaderPosArray.put(realPosition, new ClickInfo(bottom));
                }
            } else {
                //绘制分割线
                drawDivide(c, parent, childView, realPosition, left, right);
            }
        }
    }


    /**
     * 绘制悬浮框
     *
     * @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 = getGroupName(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 组名
     */
    @Override
    String getGroupName(int realPosition) {
        if (mGroupListener != null) {
            return mGroupListener.getGroupName(realPosition);
        } else {
            return null;
        }
    }


    public static class Builder {
        private StickyDecoration mDecoration;

        private Builder(GroupListener groupListener) {
            mDecoration = new StickyDecoration(groupListener);
        }

        public static Builder init(GroupListener groupListener) {
            return new Builder(groupListener);
        }

        /**
         * 设置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 height 高度
         * @return this
         */
        public Builder setDivideHeight(int height) {
            mDecoration.mDivideHeight = height;
            return this;
        }

        /**
         * 设置分割线颜色
         *
         * @param color color
         * @return this
         */
        public Builder setDivideColor(@ColorInt int color) {
            mDecoration.mDivideColor = color;
            mDecoration.mDividePaint.setColor(color);
            return this;
        }

        /**
         * 设置点击事件
         *
         * @param listener 点击事件
         * @return this
         */
        public Builder setOnClickListener(OnGroupClickListener listener) {
            mDecoration.setOnGroupClickListener(listener);
            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;
        }

        public StickyDecoration build() {
            return mDecoration;
        }
    }
}

4. 数据类

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

CityUtil.java

public class CityUtil {
    private static final String[] CITYS = {"福建省", "安徽省", "浙江省", "江苏省"};

    /**
     * 获取城市名
     *
     * @return
     */
    public static List<City> getCityList() {
        List<City> dataList = new ArrayList<>();
        final String FU_JIAN = CITYS[0];
        final int FU_JIAN_ICON = R.mipmap.city1;
        dataList.add(new City("福州", FU_JIAN, FU_JIAN_ICON));
        dataList.add(new City("厦门", FU_JIAN, FU_JIAN_ICON));
        dataList.add(new City("泉州", FU_JIAN, FU_JIAN_ICON));
        dataList.add(new City("宁德", FU_JIAN, FU_JIAN_ICON));
        dataList.add(new City("漳州", FU_JIAN, FU_JIAN_ICON));
        final String AN_HUI = CITYS[1];
        final int AN_HUI_ICON = R.mipmap.city2;
        dataList.add(new City("合肥", AN_HUI, AN_HUI_ICON));
        dataList.add(new City("芜湖", AN_HUI, AN_HUI_ICON));
        dataList.add(new City("蚌埠", AN_HUI, AN_HUI_ICON));
        final String ZHE_JIANG = CITYS[2];
        final int ZHE_JIANG_ICON = R.mipmap.city3;
        dataList.add(new City("杭州", ZHE_JIANG, ZHE_JIANG_ICON));
        dataList.add(new City("宁波", ZHE_JIANG, ZHE_JIANG_ICON));
        dataList.add(new City("温州", ZHE_JIANG, ZHE_JIANG_ICON));
        dataList.add(new City("嘉兴", ZHE_JIANG, ZHE_JIANG_ICON));
        dataList.add(new City("绍兴", ZHE_JIANG, ZHE_JIANG_ICON));
        dataList.add(new City("金华", ZHE_JIANG, ZHE_JIANG_ICON));
        dataList.add(new City("湖州", ZHE_JIANG, ZHE_JIANG_ICON));
        dataList.add(new City("舟山", ZHE_JIANG, ZHE_JIANG_ICON));
        final String JIANG_SU = CITYS[3];
        final int JIANG_SU_ICOM = R.mipmap.city4;
        dataList.add(new City("南京", JIANG_SU, JIANG_SU_ICOM));
        return dataList;
    }


    /**
     * 获取城市名
     *
     * @return
     */
    public static List<City> getRandomCityList() {
        List<City> dataList = new ArrayList<>();
        Random random = new Random();
        int provinceSize = random.nextInt(5) + 3;
        for (int i = 0; i < provinceSize; i++) {
            String province = getRandomCityName();
            int citySize = random.nextInt(3) + 1;
            for (int j = 0; j < citySize; j++) {
                dataList.add(new City(province + " : city " + j, province, R.mipmap.city4));
            }
        }
        return dataList;
    }

    private static String getRandomCityName() {
        Random random = new Random();
        return CITYS[random.nextInt(4)];
    }
}

5. MyRecyclerView.java

public class MyRecyclerView extends RecyclerView {
    private BaseDecoration mDecoration;

    public MyRecyclerView(Context context) {
        super(context);
    }

    public MyRecyclerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public MyRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public void addItemDecoration(ItemDecoration decor) {
        if (decor != null && decor instanceof BaseDecoration) {
            mDecoration = (BaseDecoration) decor;
        }
        super.addItemDecoration(decor);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent e) {
        if (mDecoration != null) {
            switch (e.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    mDecoration.onEventDown(e);
                    break;
                case MotionEvent.ACTION_UP:
                    if (mDecoration.onEventUp(e)) {
                        return true;
                    }
                    break;
                default:
            }
        }
        return super.onInterceptTouchEvent(e);
    }
}

6. StickyActivity.java

public class StickyActivity extends BaseActivity {
    @BindView(R.id.rv)
    MyRecyclerView mRecyclerView;

    QuickAdapter mAdapter;
    List<City> dataList = new ArrayList<>();

    @Override
    protected int getLayoutId() {
        return R.layout.activity_sticky;
    }

    @Override
    protected void initView() {
        //模拟数据
        dataList.addAll(CityUtil.getCityList());
        dataList.addAll(CityUtil.getCityList());

        StickyDecoration decoration = StickyDecoration.Builder
                .init(new GroupListener() {
                    @Override
                    public String getGroupName(int position) {
                        //组名回调
                        if (dataList.size() > position && position > -1) {
                            //获取组名,用于判断是否是同一组
                            return dataList.get(position).getProvince();
                        }
                        return null;
                    }
                })
                .setGroupBackground(Color.parseColor("#48BDFF"))
                .setGroupHeight(DensityUtil.dip2px(this, 35))
                .setDivideColor(Color.parseColor("#EE96BC"))
                .setDivideHeight(DensityUtil.dip2px(this, 2))
                .setGroupTextColor(Color.BLACK)
                .setGroupTextSize(DensityUtil.sp2px(this, 15))
                .setTextSideMargin(DensityUtil.dip2px(this, 10))
                .setOnClickListener(new OnGroupClickListener() {
                    @Override
                    public void onClick(int position, int id) {                                 //Group点击事件
                        String content = "onGroupClick --> " + dataList.get(position).getProvince();
                        Toast.makeText(StickyActivity.this, content, Toast.LENGTH_SHORT).show();
                    }
                })
                .build();

        mAdapter = new QuickAdapter();
        mAdapter.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(@NonNull BaseQuickAdapter<?, ?> adapter, @NonNull View view, int position) {
                City city = dataList.get(position);
                Toast.makeText(StickyActivity.this,
                        "item click " + position + " : " + city.getProvince() + " - " + city.getName(),
                        Toast.LENGTH_SHORT).show();
            }
        });


        RecyclerView.LayoutManager manager;
        manager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
        // header
        TextView header = new TextView(this);
        header.setText("header");
        header.setGravity(Gravity.CENTER);
        ViewGroup.MarginLayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 200);
        header.setLayoutParams(params);
        //((QuickAdapter) mAdapter).addHeaderView(header);
        decoration.resetSpan(mRecyclerView, new GridLayoutManager(this, 3));
        mRecyclerView.setLayoutManager(manager);
        mRecyclerView.addItemDecoration(decoration);
        mRecyclerView.setAdapter(mAdapter);
    }

    class QuickAdapter extends BaseQuickAdapter<City, BaseViewHolder> {
        public QuickAdapter() {
            super(R.layout.item_recycler_view, dataList);
        }

        @Override
        protected void convert(@Nullable BaseViewHolder holder, City item) {
            holder.setText(R.id.tv, item.getName());
        }
    }
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kevin-Dev

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值