RecyclerView详解

                                               RecyclerView详解

集成:   必须手动导入带有RecyclerView的V7包

结构:

            RecyclerView.Adapter: 创建View并将数据集合绑定到View上

           ViewHolder: 持有所有的用于绑定数据或者需要操作的View

           LayoutManager: 布局管理器,负责摆放视图等相关操作

            ItemDecoration: 负责绘制Item附近的分割线,通过RecyclerView.addItemDecoration()使用

            ItemAnimator: 为Item的操作添加动画效果,如,增删条目等,通过RecyclerView.setItemAnimator(new DefaultItemAnimator());使用

RecyclerView的内置管理器

         · LinearLayoutManager:以垂直或水平滚动列表方式显示项目。类似Listview

·         GridLayoutManager: 在网格中显示项目。                 类似GridView

·         StaggeredGridLayoutManager: 在分散对齐网格中显示项目  瀑布流

          继承RecyclerView.LayoutManager 就可以创建自定义的布局管理器。

RecyclerView.ItemDecoration是一个抽象类,可以通过重写以下三个方法,来实现Item之间的偏移量或者装饰效果:

          public void onDraw(Canvas c, RecyclerViewparent) 装饰的绘制在Item条目绘制之前调用,所以这有可能被Item的内容所遮挡

          public void onDrawOver(Canvas c, RecyclerViewparent) 装饰的绘制在Item条目绘制之后调用,因此装饰将浮于Item之上

          public void getItemOffsets(Rect outRect,int itemPosition, RecyclerView parent) 与padding或margin类似,LayoutManager在测量阶段会调用该方法,计算出每一个Item的正确尺寸并设置偏移量。

ItemAnimator触发于以下三种事件:

    某条数据被插入到数据集合中

    从数据集合中移除某条数据

    更改数据集合中的某条数据


在之前的版本中,当时据集合发生改变时通过调用notifyDataSetChanged(),来刷新列表,因为这样做会触发列表的重绘,所以并不会出现任何动画效果,因此需要调用一些以notifyItem*()作为前缀的特殊方法,比如:

 

    public final void notifyItemInserted(intposition) 向指定位置插入Item

    public final void notifyItemRemoved(intposition) 移除指定位置Item

    public final void notifyItemChanged(intposition) 更新指定位置Item

六优点
     它自带ViewHolder来实现View的复用机制,再也不用ListView那样在getView()里自己写了
     使用LayoutManager可以实现ListView,GridView以及流式布局的列表效果
     通过setItemAnimator(ItemAnimator animator)可以实现增删动画(懒的话,可以使用默认的ItemAnimator对象,效果也不错)
     控制item的间隔,可以使用addItemDecoration(ItemDecoration decor),不过里边的ItemDecoration是一个抽象类,需要自己去实现

RecyclerView的常用方法

1  GetChildCount();        //获取可见的item数量

2. findViewHolderForAdapterPosition      //获取position处item绑定的viewHolder

3  设置固定大小   recyclerView_one.setHasFixedSize(true);
                                                                                              布局管理器之GridLayoutManager

一构造方法GridLayoutManager,网格布局(流式布局应该是它的一个特殊情况):
GridLayoutManager(Context context, int spanCount)或
GridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout)
        1 Context context上下文
        2 int spanCount  显示的个数
        3 int orientation  显示的类型    默认为vertical
        LinearLayoutManager.VERTICAL  整体竖直排列一行显示参数二设置的个数
        LinearLayoutManager.HORIZONTAL 整体水平排一列显示spanCount  个数据
4 boolean reverseLayout最后一个参数表示的是是否逆向布局(意思是将数据反向显示,原先从左向右,从上至下。设为true之后全部逆转)。

小提示:在这两个LayoutManager中,默认的orientation为vertical,reverseLayout为false。对应的参数在GridLayoutManager中都有对应的方法来进行补充设置。而在StaggeredGridLayoutManager中所有的方法都针对reverseLayout做了判断,然而它并没有给出这个参数设定值的api。

二常用实现复杂列数变化的方法    根据position控制每列显示的多少

mGridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
            @Override
            public int getSpanSize(int position) {
             return  4 ? mGridLayoutManager.getSpanCount() : 1;
            }
});

当前position为4吗  不为4  每设置的显示类型每行【或列】显示构造方法里设置的个数【mGridLayoutManager.getSpanCount()获取GridLayoutManager设置的个数】   为4该下标position显示一条数据每行【或列】

                                                                       布局管理器之LinearLayoutManager

可见性:在RecyclerView里可见性的定义指的是Item露出一部分,,这个Item就是可见性的
完全可见性:指的是整个Item都可以在屏幕里展示出来,,没有被别的控件遮挡
一常用方法
1findFirstVisibleItemPosition();  获取第一个可见item的pisition
2findFirstCompletelyVisibleItemPosition();获取第一个完全可见item的position
3findLastVisibleItemPosition();  获取最后第一个可见item的pisition
4findFirstCompletelyVisibleItemPosition();获取最后一个完全可见item的position
5.setOrientation(OrientationHelper.VERTICAL);   //设置垂直方向
                                                                 

                                                                       瀑布流管理器

 mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(4,        StaggeredGridLayoutManager.VERTICAL));

 这样就和GridLayoutManager实现一样的效果了

 瀑布流效果在适配器设置其高度不一致即可

                                                                       RecyclerView.ItemDecoration画分割线

RecyclerView.ItemDecoration是一个抽象类,可以通过重写以下三个方法,来实现Item之间的偏移量或者装饰效果:

方法一:   public void onDraw(Canvas c, RecyclerViewparent) 装饰的绘制在Item条目绘制之前调用,所以这有可能被Item的内容所遮挡

方法二:    public voidonDrawOver(Canvas c, RecyclerView parent) 装饰的绘制在Item条目绘制之后调用,因此装饰将浮于Item之上、

public class ItemDecor extends RecyclerView.ItemDecoration {
    Paint mPaint;
    public ItemDecor() {
        mPaint = new Paint();
        mPaint.setColor(0x99FF0000);
}
//此等装饰物在   item绘制之后调用   在item之上
    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        c.drawCircle(50, 30, 30, mPaint);
      }
}

//使用这个方法画分割线     需要通过遍历给每个条目画

public class ItemDecorationRec extends RecyclerView.ItemDecoration{
    //声明画笔
    Paint mPaint;
    //构造函数初始化画笔
    public ItemDecorationRec() {
        mPaint = new Paint();
        mPaint.setColor(0x99FF0000);
    }
    //上边画圆
    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        final int left = parent.getPaddingLeft();
        final int right = parent.getWidth() - parent.getPaddingRight();
        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int top = child.getBottom() + params.bottomMargin +
                    Math.round(ViewCompat.getTranslationY(child));
            final int bottom = top + 50;
            c.drawRect(left, top, right, bottom, mPaint);
        }
//        c.drawCircle(50, 30, 30, mPaint);
    }
    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state);
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        outRect.set(0,0,0,70);
    }
}
方法三

public voidgetItemOffsets(Rect  outRect, intitemPosition, RecyclerView  parent) 与padding或margin类似,LayoutManager在测量阶段会调用该方法,计算出每一个Item的正确尺寸并设置偏移量。

参数一:我们通过设置outRect的left, top, right, bottom属性值就可以让ItemView产生相应的偏移(内嵌),
上述方法的调用顺序,先执行ItemDecoration的onDraw()、再执行ItemView的onDraw()、再执行ItemDecoration的onDrawOver()。由于和RecyclerView使用的是同一个Canvas,所以你想在Canvas上画什么都可以,就像我们平时自定义View时写onDraw()方法一样。
二 使用:自定义类itemDecoration继承RecyclerView.ItemDecoration重写上面三个方法即可
         然后调用mRecycler.addItemDecoration(new ItemDecorationRec());即可给条目添加间隔  【可重复添加addItemDecoration】

三 使用系统自带的画分割线

public class SystemDecoration extends RecyclerView.ItemDecoration {
    //采用系统内置的风格的分割线
    private static final int[] attrs=new int[]{android.R.attr.listDivider};  
    private Drawable mDivider;
    private int orientation;  //定向横向还是竖向的

    /**
     *  系统自制分割线   参数二是orientation传入横向还是纵向的
     */
    public SystemDecoration(Context context,int orientation) {
        TypedArray typedArray=context.obtainStyledAttributes(attrs);
        mDivider=typedArray.getDrawable(0);
        typedArray.recycle();
        this.orientation=orientation;
    }
    
    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDrawOver(c, parent, state);
    }
    
    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        drawHDeraction(c,parent);
        drawVDeraction(c,parent);
    }
    /**
     * 绘制水平方向的分割线
     * @param c
     * @param parent
     */
    private void drawHDeraction(Canvas c,RecyclerView parent){
        int left=parent.getPaddingLeft();
        int right=parent.getWidth()-parent.getPaddingRight();
        int childCount=parent.getChildCount();
        for(int i=0;i<childCount;i++){
            View child=parent.getChildAt(i);
            RecyclerView.LayoutParams layoutParams=(RecyclerView.LayoutParams)child.getLayoutParams();
            int top=child.getBottom()+layoutParams.bottomMargin;
            int bottom=top+mDivider.getIntrinsicHeight();
            mDivider.setBounds(left,top,right,bottom);
            mDivider.draw(c);
        }
    }
    /**
     * 绘制垂直方向的分割线
     * @param c
     * @param parent
     */
    private void drawVDeraction(Canvas c,RecyclerView parent){
        int top=parent.getPaddingTop();
        int bottom=parent.getHeight()-parent.getPaddingBottom();
        int childCount=parent.getChildCount();
        for(int i=0;i<childCount;i++){
            View child=parent.getChildAt(i);
            RecyclerView.LayoutParams layoutParams=(RecyclerView.LayoutParams)child.getLayoutParams();
            int left=child.getRight()+layoutParams.rightMargin;
            int right=left+mDivider.getIntrinsicWidth();
            mDivider.setBounds(left,top,right,bottom);
            mDivider.draw(c);
        }
    }
    @Override
    public void getItemOffsets(Rect outRect,View view, RecyclerView parent, RecyclerView.State state) {
        if(OrientationHelper.HORIZONTAL==orientation){
            outRect.set(0, 0,mDivider.getIntrinsicWidth(), 0);
        }else {
            outRect.set(0, 0, 0,mDivider.getIntrinsicHeight());
        }
    }
}
}
调用:recyclerView_one.addItemDecoration(newAdvanceDecoration(this,OrientationHelper.VERTICAL))
GrideDecoration   网格布局用的分割线
public class grideDecoration extends RecyclerView.ItemDecoration {
    private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
    private Drawable mDivider;

    public grideDecoration(Context context) {
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
    }
    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {

        drawHorizontal(c, parent);
        drawVertical(c, parent);

    }

    private int getSpanCount(RecyclerView parent) {
        // 列数
        int spanCount = -1;
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {

            spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {
            spanCount = ((StaggeredGridLayoutManager) layoutManager)
                    .getSpanCount();
        }
        return spanCount;
    }

    public void drawHorizontal(Canvas c, RecyclerView parent) {
        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int left = child.getLeft() - params.leftMargin;
            final int right = child.getRight() + params.rightMargin
                    + mDivider.getIntrinsicWidth();
            final int top = child.getBottom() + params.bottomMargin;
            final int bottom = top + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    public void drawVertical(Canvas c, RecyclerView parent) {
        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);

            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int top = child.getTop() - params.topMargin;
            final int bottom = child.getBottom() + params.bottomMargin;
            final int left = child.getRight() + params.rightMargin;
            final int right = left + mDivider.getIntrinsicWidth();

            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    private boolean isLastColum(RecyclerView parent, int pos, int spanCount,
                                int childCount) {
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边
            {
                return true;
            }
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {
            int orientation = ((StaggeredGridLayoutManager) layoutManager)
                    .getOrientation();
            if (orientation == StaggeredGridLayoutManager.VERTICAL) {
                if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边
                {
                    return true;
                }
            } else {
                childCount = childCount - childCount % spanCount;
                if (pos >= childCount)// 如果是最后一列,则不需要绘制右边
                    return true;
            }
        }
        return false;
    }

    private boolean isLastRaw(RecyclerView parent, int pos, int spanCount,
                              int childCount) {
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            childCount = childCount - childCount % spanCount;
            if (pos >= childCount)// 如果是最后一行,则不需要绘制底部
                return true;
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {
            int orientation = ((StaggeredGridLayoutManager) layoutManager)
                    .getOrientation();
            // StaggeredGridLayoutManager 且纵向滚动
            if (orientation == StaggeredGridLayoutManager.VERTICAL) {
                childCount = childCount - childCount % spanCount;
                // 如果是最后一行,则不需要绘制底部
                if (pos >= childCount)
                    return true;
            } else
            // StaggeredGridLayoutManager 且横向滚动
            {
                // 如果是最后一行,则不需要绘制底部
                if ((pos + 1) % spanCount == 0) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public void getItemOffsets(Rect outRect, int itemPosition,
                               RecyclerView parent) {
        int spanCount = getSpanCount(parent);
        int childCount = parent.getAdapter().getItemCount();
        if (isLastRaw(parent, itemPosition, spanCount, childCount))// 如果是最后一行,则不需要绘制底部
        {
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
        } else if (isLastColum(parent, itemPosition, spanCount, childCount))// 如果是最后一列,则不需要绘制右边
        {
            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
        } else {
            outRect.set(0, 0, mDivider.getIntrinsicWidth(),
                    mDivider.getIntrinsicHeight());
        }
    }
}
                                                                                                                              ItemAnimator
 1// 设置item默认动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
                                                                                                                               

                                                                                                                              RecyclerAdapte

一Recycler.Adapter中的数据的添加和删除

例如我们在使用ListView的时候,当数据发生变化的时候可以通过notifyDatasetChange()来刷新界面。对于RecyclerView控件来讲,给我们提供更加高级的使用方法notifyItemInserted(position)和notifyItemRemoved(position)
我们可以在TestRecyclerAdapter中添加数据新增和数据删除的方法如下:

  //添加数据  
     public void addItem(String data, intposition) {  
         mTitles.add(position, data);  
         notifyItemInserted(position);  
     } 

 //删除数据 

    public void removeItem(String data) { 

        int position = mTitles.indexOf(data); 

        mTitles.remove(position); 

         notifyItemRemoved(position); 

     }
在运行之前我们不要忘记RecyclerView给提供了动画设置,我这边就直接采用了默认动画,设置方法如下:

 //添加默认的动画效果 

 recyclerView_one.setItemAnimator(new DefaultItemAnimator());

二适配器的实现方法

//自定义适配器  继承  RecyclerView.Adapter   重写几个方法
public class MyRecyclerAdapter extends RecyclerView.Adapter {
    private static final int ITEM_VIEW_TYPE_HEADER = 12;
    private static final int ITEM_VIEW_TYPE_ITEM = 1;
    private List<MOdule> list;//
    private Context context;
    private List<Activity> activityList;//activity的集合
    private BitmapUtils bitmapUtils;
    private int w;//屏幕宽度
    private int size;//添加空白item的集合长度
    private User_login user;

    ViewHolder viewHolderholder;
    Holder mholder;

    public boolean isHeader(int position) {
        return position == 12;
    }
    /**
     *  适配器的构造函数
     */

    public MyRecyclerAdapter(List<MOdule> list, Context context, int w, List<Activity> activityList, int size) {
        this.list = list;
        this.context = context;
        this.w = w;
        this.activityList = activityList;
        this.size = size;
    }

    /**
     *  onCreateViewHolder会调用这个根据position获取该位置下    条目的类型    然后onCreateViewHolder根据type分别创建holder
     */
    @Override
    public int getItemViewType(int position) {
        if (position == 12) {
            return ITEM_VIEW_TYPE_HEADER;
        } else {
            return ITEM_VIEW_TYPE_ITEM;
        }
    }


     /**
      * 是用来配合写好的ViewHolder来返回一个ViewHolder对象。这里也涉及到了条目布局的加载。viewType则表示需要给当前position生成的是哪一种ViewHolder,这个参数也说明了RecyclerView对多类型ItemView的支持。
      */
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == ITEM_VIEW_TYPE_HEADER) {
            //ViewPager的布局
            View itemview_item2 = LayoutInflater.from(context).inflate(R.layout.recycler_item2, parent, false);
            mholder = new Holder(itemview_item2);
            ViewGroup.LayoutParams params = mholder.itemView.getLayoutParams();
            params.width = w;
            params.height = (int) ((1f / 4f) * w);
            return mholder;
        } else {    //创建普通的方块+
            final Context context = parent.getContext();
            //GridView的布局
            View itemview_item1 = LayoutInflater.from(context).inflate(R.layout.recycler_item1, parent, false);

            viewHolderholder = new ViewHolder(itemview_item1);

            return viewHolderholder;
        }
    }


    /**
     *   专门用来绑定ViewHolder里的控件和数据源中position位置的数据。
     */
    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
        if (position != ITEM_VIEW_TYPE_HEADER && position < list.size() - size) {
            viewHolderholder = (ViewHolder) holder;

            /**
             *  通过viewHolderholder.itemView.   设置条目的长按点击事件
             */
 
            viewHolderholder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    //添加震动
                    Vibrator vibrator = (Vibrator) (context.getSystemService(Context.VIBRATOR_SERVICE));
                    long[] pattern = {20, 50};
                    vibrator.vibrate(pattern, -1);
                    //添加缩放动画
//                    ScaleAnimation animation=new ScaleAnimation(1.0f,1.2f,1.0f,1.2f);
//                    animation.setDuration(200);
//                    animation.setFillAfter(false);
//                    v.startAnimation(animation);
                    //     v.setBackgroundColor(Color.parseColor("#E8E6E8"));
                    //记录位置表示有长按操作
                    SharedPreferencesUtil.putInt("recycler_position", position, context);
                    return false;
                }
            });
            
            /**
             *  通过viewHolderholder.itemView.   设置条目的点击事件
             */
            
            viewHolderholder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    int recycler_position = SharedPreferencesUtil.getInt("recycler_position",
                            context);
                    
              
                }
            });
            tv.setText(list.get(position).getModuleName());
        } else if (position == ITEM_VIEW_TYPE_HEADER) {
            mholder = (Holder) holder;
        }

    }
     /**
      *    getItemCount()就不必多说了,和ListView是一样的 条目的总个数
      */
    @Override
    public int getItemCount() {
        return list.size();
    }

    /**
     * GridView  每个方块的 ViewHolder    把inflate后的view传入
     * 
     */
    class ViewHolder extends RecyclerView.ViewHolder implements ItemTouchHelperViewHolder {
        private View view;

        public ViewHolder(View itemView) {
            super(itemView);
            this.view = itemView;
        }

        public View getView() {
            return view;
        }

        @Override
        public void onItemSelected() {

            // 当选中时,背景色为灰色
            itemView.setBackgroundColor(Color.LTGRAY);
        }

        @Override
        public void onItemClear() {

            //当拖拽完毕后,背景色为透明
            itemView.setBackgroundColor(0);
        }
    }

    /**
     * ViewPager
     * Holder
     */

     class Holder extends RecyclerView.ViewHolder {
        public Holder(View itemView) {
            super(itemView);
        }
     }
}

三 adapter中的数据的重新处理

class MyViewHolder extends ViewHolder{
   TextView tv;        
   //构造里执行findviewByid
   public MyViewHolder(Context context, View view){
          super(view);
          tv = (TextView) view.findViewById(R.id.id_num);

          //当然,我们也可以在这里使用view来对RecyclerView的一个item进行事件监听,也可以使用  
          //tv等子控件来实现item的子控件的事件监听。这也是我之所以要传context的原因之一呢~
          ......
   }
   
   //创建实例的时候    填充布局   
   public static MyViewHolder newInstance(Activity context, ViewGroup parent){
           View view = LayoutInflater.from(
              context).inflate(R.layout.item_home, parent,false);
         return new MyViewHolder(context, view);
   }
  }    

  //你没看错,数据绑定也被整合进来了,  
  //将adapter里的数据根据position获取到后传进来。当然,也可以根据具体情况来做调整。
   public void onBinViewHolder(String data){     
       tv.setText(data);//既然这里也有子控件,那么这里也可以做item子控件的事件监听喽
}
Adapter
class HomeAdapter extends RecyclerView.Adapter<MyViewHolder>{
  @Override
  public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType){//如需要,还要对viewType做判断
      return MyViewHolder.newInstance(this, parent)
  }

  @Override
  public void onBindViewHolder(MyViewHolder holder, int position){
      holder.onBindViewHolder(mDatas.get(position));
  }

  @Override
  public int getItemCount(){
      return mDatas.size();
  }
}
                                                                                                        

                                                                                    ItemTouchHelper实现Recycler的滑动和拖动

1、ItemTouchHelper   支持RecyclerView滑动删除和拖拽的工具类

结合recyvlerVIew的使用方法为

//1设置一个ItemTouchHelper.Callback对象

ItemTouchHelper.Callback callback = newItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.RIGHT| ItemTouchHelper.LEFT, 0)

//2创建  ItemTouchHelper对象     传入callBack

ItemTouchHelper itemTouchHelper=newItemTouchHelper(callback);

//3让item的图所动滑动依附在RecyclerView上

itemTouchHelper.attachToRecyclerView(mRecycler)

SimpleCallback方法

SimpleCallback构造方法需要我们传入两个参数:

1、dragDirs - 表示拖拽的方向,有六个类型的值:LEFT、RIGHT、START、END、UP、DOWN

2、swipeDirs - 表示滑动的方向,有六个类型的值:LEFT、RIGHT、START、END、UP、DOWN

这两个参数如果为0表示不执行此操作

//1设置一个ItemTouchHelper.Callback对象
 ItemTouchHelper.Callback callback = new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.RIGHT | ItemTouchHelper.LEFT, 0) {  
           /**
             * @param recyclerView
             * @param viewHolder 拖动的ViewHolder
             * @param target 目标位置的ViewHolder
             * @return
             */
            @Override
            public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,  RecyclerView.ViewHolder target) {
                int fromPosition = viewHolder.getAdapterPosition();//得到拖动ViewHolder的position
                int toPosition = target.getAdapterPosition();//得到目标ViewHolder的position
                if (fromPosition < toPosition) {
                    //分别把中间所有的item的位置重新交换
                    for (int i = fromPosition; i < toPosition; i++) {
                        Collections.swap(datas, i, i + 1);
                    }
                } else {
                    for (int i = fromPosition; i > toPosition; i--) {
                        Collections.swap(datas, i, i - 1);
                    }
                }
                mAdapter.notifyItemMoved(fromPosition, toPosition);
                //返回true表示执行拖动
                return true;
            }

            /**
             *    滑动时执行该方法     执行删除
             */
            @Override
            public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
                int position = viewHolder.getAdapterPosition();
                datas.remove(position);
                mAdapter.notifyItemRemoved(position);
            }


            /**
             *    getMovementFlags ()返回支持哪些方向的事件(貌似拖动排序事件和左右滑动事件不能同时支持,拖动会覆盖左右滑动)
             *     该方法第一个被调用   可加判断哪些可以拖动滑动   哪些不可以
             */
            @Override
            public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
                Log.d("flag","-------------------------getMovementFlags执行了");
                if (viewHolder.getAdapterPosition() == 12 || viewHolder.getAdapterPosition() >  
moduleListSize - 1) {
                    return makeMovementFlags(0, 0);   //第13个轮播 和空白页不能操作
                } else {
                    if (recyclerView.getLayoutManager() instanceof GridLayoutManager) {
                        final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN |  
ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
                        final int swipeFlags = 0;
                        return makeMovementFlags(dragFlags, swipeFlags);  //gridLayout不能滑动只能拖动
                    } else {
                        final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
                        final int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
                        return makeMovementFlags(dragFlags, swipeFlags);
                    }
                }
            }


            /**
             *  来改变动画效果,细心的会发现上图在滑动时候并没有透明感,于是我们可以实现onChildDraw()方法,该方法用于Item的绘制,actionState有三种状态SWIPE(滑动)、IDLE(静止)、DRAG(拖动)
             */
             @Override
            public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,  
float dX, float dY, int actionState, boolean isCurrentlyActive) {
                super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
                Log.d("flag", "-------------------------onChildDraw执行了");
                if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {   //ACTION_STATE_SWIPE是滑动的时候 
改变透明度
                    //左右滑动时改变Item的透明度(没用到)
                    final float alpha = 1 - Math.abs(dX) / (float) viewHolder.itemView.getWidth();
                    viewHolder.itemView.setAlpha(alpha);
                    viewHolder.itemView.setTranslationX(dX);
                }
            }

           
            /**
             *   //当选中Item时候会调用该方法,重写此方法可以实现选中时候的一些动画逻辑
             *    第二个调用
             */
            @Override
            public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
                super.onSelectedChanged(viewHolder, actionState);
                Log.d("flag", "-------------------------onSelectedChanged执行了");
                //长按  设置了放大的动画效果
                if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
                    viewHolder.itemView.setScaleX(1.2f);
                    viewHolder.itemView.setScaleY(1.2f);
                }
            }


            /**
             *   //当动画已经结束的时候调用该方法,重写此方法可以实现恢复Item的初始状态
             */
            @Override
            public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
                super.clearView(recyclerView, viewHolder);
                Log.d("flag", "------------------------clearView执行了");
                //还原动画
                viewHolder.itemView.setBackgroundResource(R.drawable.background_drag);
                viewHolder.itemView.setScaleX(1.0f);
                viewHolder.itemView.setScaleY(1.0f);
                adapter.notifyDataSetChanged();//没看出什么用
            }
}








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值