android

RecyclerView的ItemDecoration总结

2017-09-06  本文已影响384人  西西邱

一、RecyclerView.ItemDecoration 基本用法

    public class TestDividerItemDecoration extends RecyclerView.ItemDecoration {

        // 方法1:getItemOffsets (每出现一个position,调用一次)
        // 作用:设置ItemView的内嵌偏移长度(inset),相当于增加itemview的paddingLeft,paddingTop, paddingRight, paddingBottom
        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            //获取当前item位置
            //int position = parent.getChildAdapterPosition(view);
            //获取item数目
            //int itemCount = parent.getAdapter().getItemCount();
            if (mOrientation == VERTICAL){
                outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
            }else {
                outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
            }
        }

        // 作用:在绘制itemView之前,通过一系列c.drawXXX()方法绘制我们需要的内容
        // 绘制图层在ItemView以下,所以如果绘制区域与ItemView区域相重叠,会被遮挡
        @Override
        public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
            if (mOrientation == VERTICAL){
                drawVertical(c,parent,state);
            }else {
                drawHorizontal(c,parent,state);
            }
        }

        private void drawVertical(Canvas c, RecyclerView parent, RecyclerView.State state) {
            c.save();//保存Canvas
            int left;
            int right;
            //getClipToPadding是否限制在Padding绘制item--默认=true
            if (parent.getClipToPadding()){
                left = parent.getPaddingLeft();
                right = parent.getWidth() - parent.getPaddingRight();
                c.clipRect(left, parent.getPaddingTop(), right,parent.getHeight()- parent.getPaddingBottom());
            }else {
                left = 0;
                right = parent.getWidth();
            }
            //绘制
            int itemCount = parent.getChildCount();
            for (int i = 0; i < itemCount; i++) {
                View childAt = parent.getChildAt(i);
            /* getDecoratedBoundsWithMargins点进去的源码
             * mBounds.left = view.getLeft() - insets.left - lp.leftMargin
             * view.getLeft() == itemView的左边距横坐标
             * insets.left()  == itemView所有Decoration left 之和
             * lp.leftMargin  == itemView的MarginLeft的大小
             */
                parent.getDecoratedBoundsWithMargins(childAt,mBounds);
            /*mBounds.bottom == itemView底坐标+ insets.bottom()(Decoration bottom之和)+ itemView的MarginBottom
             *Math.round(ViewCompat.getTranslationY(childAt))
             */
                int bottom =  mBounds.bottom + Math.round(ViewCompat.getTranslationY(childAt));
                int top = bottom - mDivider.getIntrinsicHeight();
                mDivider.setBounds(left, top, right, bottom);
                mDivider.draw(c);
            }
            c.restore();
        }

        // 作用:onDrawOver与onDraw类似,只不过在绘制itemView之后绘制,具体表现形式,就是绘制的内容在itemview上层。
        @Override
        public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
            Log.e(TAG, "onDrawOver" );
        }
    }

二、RecyclerView时光轴效果

菜鸟裹裹时光轴效果:地址

944365-b285d251fbd87e71.png

三、微信通讯录分组悬浮效果

RecyclerView悬浮效果(代码少容易理解):地址
RecyclerView悬停头部的分组列表(进阶):地址

四、一个BUG

注意:做一个一个小实验
代码:我们设置ItemView的outRect四个方向上的偏移量

   public void getItemOffsets(){
   int positionB = parent.getChildAdapterPosition(view);
  //只给B位置设置偏移量
        if (positionB == 1){
          //四个方向上偏移量都是100
            outRect.set(100,100,100,100);
        }
}

运行结果:如下图(这里的Orientation为LinearLayoutManager.VERTICAL)

QQ截图20170906144948.png

注意看B的宽高
结论:getItemOffsets()方法设置ItemView内嵌矩形偏移值会导致
1、不能滑动方向上ItemView的长度被压缩
2、能滑动方向上ItemView的长度不变

我们看下RecyclerView的measureChild()源码找答案:

    **RecyclerView**
    public void measureChild(View child, int widthUsed, int heightUsed) {
        ...
        //这里Child的宽高和canScroll(该方向能否滑动)有关,具体的测量方式可以自己去看
        final int widthSpec =    getChildMeasureSpec(..., boolean canScroll);
        final int heightSpec =    getChildMeasureSpec(..., boolean canScroll);
        ...
        child.measure(widthSpec, heightSpec);
    }
上一篇下一篇

猜你喜欢

热点阅读