zoukankan      html  css  js  c++  java
  • RecyclerView.ItemDecoration

    decoration 英文意思:

    英[ˌdekəˈreɪʃn] 美[ˌdɛkəˈreʃən] n. 装饰品; 装饰,装潢; 装饰图案,装饰风格; 奖章;

    [例句]The decoration and furnishings had to be practical enough for a family home 房子的装潢和家具都必须很实用,适合家居生活。 [

    其他] 复数:decorations

    RecyclerView.ItemDecoration 装饰类,都装饰啥?

    RecyclerView.ItemDecoration装饰的目标当然是RecyclerView里面每个item.

    之前ListView有divier属性可以修改分隔线的样式

    RecyclerView则是提供了

    recyclerView.addItemDecoration()

     看一下源码:

       public static abstract class ItemDecoration {
            /**
             * Draw any appropriate decorations into the Canvas supplied to the RecyclerView.
             * Any content drawn by this method will be drawn before the item views are drawn,
             * and will thus appear underneath the views.
             *
             * @param c Canvas to draw into
             * @param parent RecyclerView this ItemDecoration is drawing into
             * @param state The current state of RecyclerView
             */
            public void onDraw(Canvas c, RecyclerView parent, State state) {
                onDraw(c, parent);
            }
    
            /**
             * @deprecated
             * Override {@link #onDraw(Canvas, RecyclerView, RecyclerView.State)}
             */
            @Deprecated
            public void onDraw(Canvas c, RecyclerView parent) {
            }
    
            /**
             * Draw any appropriate decorations into the Canvas supplied to the RecyclerView.
             * Any content drawn by this method will be drawn after the item views are drawn
             * and will thus appear over the views.
             *
             * @param c Canvas to draw into
             * @param parent RecyclerView this ItemDecoration is drawing into
             * @param state The current state of RecyclerView.
             */
            public void onDrawOver(Canvas c, RecyclerView parent, State state) {
                onDrawOver(c, parent);
            }
    
            /**
             * @deprecated
             * Override {@link #onDrawOver(Canvas, RecyclerView, RecyclerView.State)}
             */
            @Deprecated
            public void onDrawOver(Canvas c, RecyclerView parent) {
            }
    
    
            /**
             * @deprecated
             * Use {@link #getItemOffsets(Rect, View, RecyclerView, State)}
             */
            @Deprecated
            public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
                outRect.set(0, 0, 0, 0);
            }
    
            /**
             * Retrieve any offsets for the given item. Each field of <code>outRect</code> specifies
             * the number of pixels that the item view should be inset by, similar to padding or margin.
             * The default implementation sets the bounds of outRect to 0 and returns.
             *
             * <p>
             * If this ItemDecoration does not affect the positioning of item views, it should set
             * all four fields of <code>outRect</code> (left, top, right, bottom) to zero
             * before returning.
             *
             * <p>
             * If you need to access Adapter for additional data, you can call
             * {@link RecyclerView#getChildAdapterPosition(View)} to get the adapter position of the
             * View.
             *
             * @param outRect Rect to receive the output.
             * @param view    The child view to decorate
             * @param parent  RecyclerView this ItemDecoration is decorating
             * @param state   The current state of RecyclerView.
             */
            public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) {
                getItemOffsets(outRect, ((LayoutParams) view.getLayoutParams()).getViewLayoutPosition(),
                        parent);
            }
        }
    View Code

    会发现主要有下面三个方法:

    public void onDraw(Canvas c, RecyclerView parent, State state)
    public void onDrawOver(Canvas c, RecyclerView parent, State state)
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state)
     
    那来看看都什么意思干么用:
    直接看注释吧
    onDraw():
    /**
    * Draw any appropriate decorations into the Canvas supplied to the RecyclerView.
    * Any content drawn by this method will be drawn before the item views are drawn, * and will thus appear underneath the views. *
    * @param c Canvas to draw into * @param parent RecyclerView this ItemDecoration is drawing into * @param state The current state of RecyclerView */  

    大概是说会在item画之前画些东西,会现在Item下面。那相当于是一个背景。

     onDrawOver()

      /**
             * Draw any appropriate decorations into the Canvas supplied to the RecyclerView.
             * Any content drawn by this method will be drawn after the item views are drawn
             * and will thus appear over the views.
             *
             * @param c Canvas to draw into
             * @param parent RecyclerView this ItemDecoration is drawing into
             * @param state The current state of RecyclerView.
             */
            public void onDrawOver(Canvas c, RecyclerView parent, State state) {
                onDrawOver(c, parent);
            }
    will be drawn after the item views are drawn and will thus appear over the views.
    很明白与上面的相对,会有Item画完之后去画,在浮在item内容上面。

    getItemOffsets()
     /**
             * Retrieve any offsets for the given item. Each field of <code>outRect</code> specifies
             * the number of pixels that the item view should be inset by, similar to padding or margin.
             * The default implementation sets the bounds of outRect to 0 and returns.
             *
             * <p>
             * If this ItemDecoration does not affect the positioning of item views, it should set
             * all four fields of <code>outRect</code> (left, top, right, bottom) to zero
             * before returning.
             *
             * <p>
             * If you need to access Adapter for additional data, you can call
             * {@link RecyclerView#getChildAdapterPosition(View)} to get the adapter position of the
             * View.
             *
             * @param outRect Rect to receive the output.
             * @param view    The child view to decorate
             * @param parent  RecyclerView this ItemDecoration is decorating
             * @param state   The current state of RecyclerView.
             */
            public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) {
                getItemOffsets(outRect, ((LayoutParams) view.getLayoutParams()).getViewLayoutPosition(),
                        parent);
            }

    也说得很明白:similar to padding or margin.跟padding margin相似。给设置边距的。

    从getItemOffsets()来开始实践

    我们给recyclerview 加上背景以便观察。

    <android.support.v7.widget.RecyclerView
    android:id="@+id/rcv_qulitry"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#f00">
    </android.support.v7.widget.RecyclerView>

    实现在自义定的decoration类

    package com.lechang.fragment.decoration;
    
    import android.graphics.Rect;
    import android.support.v7.widget.RecyclerView;
    import android.view.View;
    
    /**
     * Created by hongtao on 2017/11/17.
     */
    
    public class MyDecoration extends RecyclerView.ItemDecoration {
    
        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            outRect.left = 5;
            outRect.right = 5;
            outRect.bottom = 10;
            super.getItemOffsets(outRect, view, parent, state);
        }
    }

    马上来用

    recyclerView.addItemDecoration(new MyDecoration());

    看看效果,嘿嘿,尼玛不是那么回事,怎么不起作用呢?

    蒙逼了?

    仔细看一下代码,方法调用了super.getItemOffsets(outRect, view, parent, state);再点进去看,

    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) {
    getItemOffsets(outRect, ((LayoutParams) view.getLayoutParams()).getViewLayoutPosition(),
    parent);
    }
    然后再调用了
    @Deprecated
    public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
    outRect.set(0, 0, 0, 0);
    }

    看到没

    outRect.set(0, 0, 0, 0);

    给设置成0了。

    那我们

           outRect.left = 5;
            outRect.right = 5;
            outRect.bottom = 10;

    设置的值就成白做了。

    所以得把这个赋值放到super之后。

    package com.lechang.fragment.decoration;
    
    import android.graphics.Rect;
    import android.support.v7.widget.RecyclerView;
    import android.view.View;
    
    /**
     * Created by hongtao on 2017/11/17.
     */
    
    public class MyDecoration extends RecyclerView.ItemDecoration {
    
        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            super.getItemOffsets(outRect, view, parent, state);
            //切记要先调super.
            outRect.left = 5;
            outRect.right = 5;
            outRect.bottom = 10;
        }
    }

    这回可以了。
    看一下效果:

    红色底出来了。相当于padding .

    只是底红露出,不能当分隔线,你非要用也行。

    主要的还是要用ondraw把分隔线画出来。

    下面来试ondraw().

    原型:如下 

    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state)

    这是一个回调的方法,给了一个画布,RecyclerView ,和RecyclerView.State

    RecyclerView.State:给了下面三个状态
    static final int STEP_START = 1;
    static final int STEP_LAYOUT = 1 << 1;
    static final int STEP_ANIMATIONS = 1 << 2;

    意思是我们可以在这三个不同时期做不同的事,画不同的东西。有需求可以安排。

     RecyclerView parent

    既然是parent 那他的child都是个个item.

    那整个方法的意思就是用Canvas c给每个item都画上装饰(分隔线)。

    来一段代码:

    package com.lechang.fragment.decoration;
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Rect;
    import android.support.v7.widget.RecyclerView;
    import android.view.View;
    
    /**
     * Created by hongtao on 2017/11/17.
     */
    
    public class MyDecoration extends RecyclerView.ItemDecoration {
    
        Paint dividerPaint;
        int dividerHeight = 3;
    
        public MyDecoration(Context context, int dividerHeight) {
            dividerPaint = new Paint();
            dividerPaint.setColor(Color.BLACK);
            this.dividerHeight = dividerHeight;
        }
    
        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            super.getItemOffsets(outRect, view, parent, state);
            //切记要先调super.
    //        outRect.left = 5;
    //        outRect.right = 5;
            outRect.bottom = 20;
        }
    
        @Override
        public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
            int childCount = parent.getChildCount();
            int left = parent.getPaddingLeft();
            int right = parent.getWidth() - parent.getPaddingRight();
    
            for (int i = 0; i < childCount - 1; i++) {
                View view = parent.getChildAt(i);
                float top = view.getBottom();
                float bottom = view.getBottom() + dividerHeight;
                //画了一个矩型
                c.drawRect(left, top, right, bottom, dividerPaint);
            }
        }
    }
    outRect.bottom 给了 20的值,要是不给这个值,那将什么也看不到。因为是在item下层的;
    最终效果:黑色线是onDraw结果,红是底



    接下来看:
    onDrawOver()方法效果
    package com.lechang.fragment.decoration;
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Rect;
    import android.support.v7.widget.RecyclerView;
    import android.view.View;
    
    /**
     * Created by hongtao on 2017/11/17.
     */
    
    public class MyDecoration extends RecyclerView.ItemDecoration {
    
        Paint dividerPaint;
        int dividerHeight = 3;
    
        public MyDecoration(Context context, int dividerHeight) {
            dividerPaint = new Paint();
            dividerPaint.setColor(Color.BLACK);
            this.dividerHeight = dividerHeight;
        }
    
        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            super.getItemOffsets(outRect, view, parent, state);
            //切记要先调super.
    //        outRect.left = 5;
    //        outRect.right = 5;
    //        outRect.bottom = 20;
        }
    
        @Override
        public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
            int childCount = parent.getChildCount();
            int left = parent.getPaddingLeft();
            int right = parent.getWidth() - parent.getPaddingRight();
    
            for (int i = 0; i < childCount - 1; i++) {
                View view = parent.getChildAt(i);
                float top = view.getBottom();
                float bottom = view.getBottom() + dividerHeight;
                //画了一个矩型
                c.drawRect(left, top, right, bottom, dividerPaint);
            }
        }
    
        @Override
        public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
            int childCount = parent.getChildCount();
            int left = parent.getPaddingLeft();
            int right = parent.getWidth() - parent.getPaddingRight();
    
            for (int i = 0; i < childCount - 1; i++) {
                View view = parent.getChildAt(i);
                float top = view.getBottom();
                float bottom = view.getBottom() + dividerHeight;
                //画了一个矩型
                c.drawRect(left, top, right, bottom, dividerPaint);
            }
        }
    }

     

    drawOver在上层画,所以不需要getItemOffsets配合。

     至此,ImtemDecoration这个类基本我们就会用了。

    如果对Item位置做一些逻辑处理,还能做出一些有意思的东西。接下来再写。告一段落。

    
    
  • 相关阅读:
    TCP流量控制,拥塞控制原理
    Java数组--求一个数组中连续m个数的和最大的数组组合
    一次使用IDEA编写JDK动态代理Class数组中有关泛型的问题
    Java数组--一个整型数组,给定一个定数,求数组中两个数的和与定数相等
    Java基础知识--Stream接口的理解与应用
    JSAP107
    JSAP106
    JSAP105
    JSAP104
    JSAP103
  • 原文地址:https://www.cnblogs.com/mamamia/p/7850405.html
Copyright © 2011-2022 走看看