RecyclerView系列(3)—ItemDirection打造粘性悬浮分组title

转载请注明出处:
http://blog.csdn.net/user11223344abc?viewmode=contents
出自【蛟-blog】

0.介绍

0.1:先看下效果图吧。
请无视titleBar,用之前的一个项目改的,懒得新建了,嘻嘻 :P

1.本文的数据格式

{
    "msg": "",
    "code": 0,
    "data": [
        {
            "key": "a",
            "items": [
                {
                    "area": null,
                    "mbile": 1499256758000
                }
            ]
        },
        {
            "key": "d",
            "items": [
                {
                    "area": null,
                    "mbile": 1499256758000
                },
                {
                    "area": null,
                    "mbile": 1499256758000
                }
            ]
        }
    ]
}

2.本文的代码结构

标出来的就是这次我们要讨论的核心。ItemDirection

ItemDirection是RecyclerView的分割线,这个属于它的一个扩展功能。

3.基本思路

我们抛开代码,用正常的逻辑来思考,是不是应该做如下3步的考虑:

3.1.找出位置

一个很重要的问题就是找出边界值的问题。试想一下,我们把一堆数据源设置进了RecyclerView,看起来就跟以前的ListView一模一样,我们要插进分割线,那么每个分割线该放在什么位置?
再回头看下我的数据格式,发现就是一个关键字拖一堆的电话号码。
也就是许多个带了标识的集合。
实际上这个分割线的位置就是每个集合的size。
(还有一种是通过一个last标识来得出边界值,但是我这里数据已经分好了就不必那么麻烦了)

3.2.在该空间内画出分类信息

自定义View。

3.3.悬浮处理

自定义View。

4.代码理解:初始化,以及三个方法

4.1:初始化的代码。

    private Paint mPaint;
    private Rect mBounds;//用于存放测量文字Rect
    private int mTitleHeight;//title的高
    private static int COLOR_TITLE_BG = Color.parseColor("#FFDFDFDF");
    private static int COLOR_TITLE_FONT = Color.parseColor("#FF000000");
    private static int mTitleFontSize;//title字体大小
    HashMap<Integer, String> keyPostMap = new HashMap<>();
    private String mKeyOnDrawOver = "";

    public StickyItemDirection(Context context, List<HotPhoneBean.DataBean> datas) {
        super();
        mPaint = new Paint();
        mBounds = new Rect();
        mTitleHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 30, context.getResources().getDisplayMetrics());
        mTitleFontSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, context.getResources().getDisplayMetrics());
        mPaint.setTextSize(mTitleFontSize);
        mPaint.setAntiAlias(true);

        HotPhoneBean.DataBean data0 = datas.get(0);
        keyPostMap.put(0, data0.getKey());

        for (int i = 0; i < datas.size(); i++) {
            HotPhoneBean.DataBean dataBean = datas.get(i);
            keyPostMap.put(dataBean.getItems().size(), dataBean.getKey());
        }
    }

4.2:找地,getItemOffsets()

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        int position = ((RecyclerView.LayoutParams) view.getLayoutParams()).getViewLayoutPosition();
        ArrayList<Integer> posList = new ArrayList<>(keyPostMap.keySet());
        if (position > -1) {
            if (posList.contains(position)) {
                outRect.set(0, mTitleHeight, 0, 0);
            } else {
                outRect.set(0, 0, 0, 0);
            }
        }
    }

4.3:画字,onDraw()

@Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state);

        Log.e("zj", "onDraw");

        final int left = parent.getPaddingLeft();
        final int right = parent.getWidth() - parent.getPaddingRight();
        final int childCount = parent.getChildCount();
        ArrayList<Integer> posList = new ArrayList<>(keyPostMap.keySet());
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
            int position = params.getViewLayoutPosition();

            if (position > -1) {
                if (posList.contains(position)) {
                    String key =  keyPostMap.get(position);
                    //drawing
                    mPaint.setColor(COLOR_TITLE_BG);
                    c.drawRect(left, child.getTop() - params.topMargin - mTitleHeight, right, child.getTop() - params.topMargin, mPaint);
                    mPaint.setColor(COLOR_TITLE_FONT);
                    mPaint.getTextBounds(key, 0, key.length(), mBounds);
                    c.drawText(key, child.getPaddingLeft(), child.getTop() - params.topMargin - (mTitleHeight / 2 - mBounds.height() / 2), mPaint);
                }
            }
        }
    }

4.4:悬浮,onDrawOver()

    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {//最后调用 绘制在最上层
        int pos = ((LinearLayoutManager) (parent.getLayoutManager())).findFirstVisibleItemPosition();
        ArrayList<Integer> posList = new ArrayList<>(keyPostMap.keySet());
        if (posList.contains(pos)) {
            mKeyOnDrawOver = keyPostMap.get(pos);
        }

        View child = parent.findViewHolderForLayoutPosition(pos).itemView;
        parent.findViewHolderForLayoutPosition(pos).itemView
        mPaint.setColor(COLOR_TITLE_BG);
        c.drawRect(parent.getPaddingLeft(), parent.getPaddingTop(), parent.getRight() - parent.getPaddingRight(), parent.getPaddingTop() + mTitleHeight, mPaint);
        mPaint.setColor(COLOR_TITLE_FONT);
        mPaint.getTextBounds(mKeyOnDrawOver, 0, mKeyOnDrawOver.length(), mBounds);
        c.drawText(mKeyOnDrawOver, child.getPaddingLeft(),
                parent.getPaddingTop() + mTitleHeight - (mTitleHeight / 2 - mBounds.height() / 2),
                mPaint);
    }

5.本文的Demo下载:

有什么问题请留言,有错误还望指出,感谢。
点击下载

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值