实现拖拽效果二: 使用RecyclerView + ItemTouchHelper 实现拖拽、删除,滑动删除效果

1,408 阅读8分钟

实现拖拽效果二: 使用RecyclerView + ItemTouchHelper 实现拖拽、删除,滑动删除效果

因为demo适配了公司的业务,具体图层不好放出来,难受。但是这毕竟只是记录学习,自己知道实现了就好!

之前是使用GridView实现的拖拽效果,但是其实他存在一个问题,当时涉及我本身的业务,所以使用那个很难实现,所以发现了这个。

GridView如果要实现横向滚动实现分页功能,并且支持拖拽互换就存在很大的问题,当然不同的trager也是可以实现的,但是很不方便,然后使用ItemTouchHelper实现就会很方便。横向滚动实现分页使用RecyclerView+ItemTouchHelper本身相较于GridView实现就简单很多,并且是google官方支持,丝毫不慌。

那么再整理思路,要完成那些方面,需要注意以下几点:

  1. 要解耦!不要一大堆文件全部卸载一两个java文件中,看着脑壳痛,让后期接手的人拿头维护。
  2. 业务需求的实现:分页和间隔。间隔必不可少,其次使用过recyclerView的都知道recyclerView是可以随意滚动的,要实现分页,像GridView+ViewPage实现效果,那就不能使得它能够随意滚动,而是一次滚动响应的列数(因为我这里是水平滚动,竖向类同)。
  3. 交互效果,也需要震动啊,改变底色啊等等
  4. 持久化,点击仿重等

这个实现方法比GridView实现着实简单很多,主要是代码的解耦啊,了解以下recyclerView和ItemTouchHelper的了解啊和具体的业务需求。

解耦

首先实现解耦,我的文件目录如下:

image-20200921102115640

从上往下分别是

  • 实现分页效果的helper
  • 适配器
  • 回调 这个就是集成itemTouchHelper.Callback,用来实现拖拽效果。
  • itemTouchHelper和适配器之间的接口,实现解耦,具体的工作全部交给适配器去做
  • 间隔

itemTouchHelper实现

itemTouchHelper是google为我们封装的为recyclerView实现的可以拖拽交换item,侧滑删除item的封装类。

我们这里要完成这个效果,主要是集成itemTouchHelper.Callback接口就行。

必须完成的有三个函数:

  • getMovementFlags :设置拖拽方向和滑动方向。
  • onMove:实现拖拽移动的时候的监听。
  • onSwiped:实现滑动删除

其次之外涉及以下几个我们需要实现的父类的函数:

  • isLongPressDragEnabled(): 是否支持长按删除 (其实不弄也许)
  • isItemViewSwipeEnable():是否支持滑动删除(其实不弄也行,但是放在自己眼皮子底下放心点)
  • onSelectdChanged():选中的时候,会调用这个方法,在这里实现长按选中的震动、改变底色效果等
  • clearView():事件结束了,Up手指了,这里也是调用实现onSelectedChanged设置底色改变的取消等操作
  • onChildDraw():这里实现自己的自定义的交互规则,或者动画效果这里也行,我这里完成了拖拽删除的自定义交互效果。

完整的源码如下,具体的注释都有:

public class MyItemTouchHelperCallback extends ItemTouchHelper.Callback {
    private MyItemTouchHelperListener mListener;	//适配器和itemTouchHelper之间的接口,完成解耦
    private boolean up;

    public MyItemTouchHelperCallback(MyItemTouchHelperListener mListener){
        this.mListener = mListener;
    }

    /**
     * 设置拖拽方向、滑动方向
     * @param recyclerView
     * @param viewHolder
     * @return
     */
    @Override
    public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
        int dragFlags = 0;
        int swipeFlags = ItemTouchHelper.UP;
        if (recyclerView.getLayoutManager() instanceof GridLayoutManager || recyclerView.getLayoutManager() instanceof StaggeredGridLayoutManager){
            dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.RIGHT | ItemTouchHelper.LEFT;
        }
        else {
            dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        }
        return makeMovementFlags(dragFlags,swipeFlags);
    }

    /**
     * 拖拽移动
     * @param recyclerView
     * @param viewHolder
     * @param target
     * @return
     */
    @Override
    public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
        int fromPosition = viewHolder.getAdapterPosition();
        int toPosition = target.getAdapterPosition();
        mListener.onItemMove(fromPosition,toPosition);
        return true;
    }

    /**
     * 滑动删除
     * @param viewHolder
     * @param direction
     */
    @Override
    public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
//        mListener.onItemDelete(viewHolder.getAdapterPosition());
    }

    /**
     * 是否支持长按拖拽
     * @return
     */
    @Override
    public boolean isLongPressDragEnabled(){
        return true;
    }

    /**
     * 是否支持滑动
     * @return
     */
    @Override
    public boolean isItemViewSwipeEnabled(){
        return false;
    }

    /**
     * 选中的时候,会调用这个方法
     * @param viewHolder
     * @param actionState
     */
    @Override
    public void onSelectedChanged(@Nullable RecyclerView.ViewHolder viewHolder, int actionState) {
        //不等于休闲的时候,也就是被选中了
        if (actionState != ItemTouchHelper.ACTION_STATE_IDLE){
            up = false;
            mListener.onSelectedItem(viewHolder);
        }
        super.onSelectedChanged(viewHolder, actionState);
    }

    /**
     * 事件结束
     * @param recyclerView
     * @param viewHolder
     */
    @Override
    public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
        mListener.onSelectedFinish(viewHolder);
        super.clearView(recyclerView, viewHolder);
    }
	/**
	* 完成自定义的交互规则
	* 完成对item拖拽到一定位置的删除
	*
	*/
    @Override
    public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
        if (mListener == null)
            return;
//        Log.d(TAG, "onChildDraw:dY " + dY);
        //因为dY是以本身为坐标的,所以只要他向上就为负的,向下就为正的,所以要
        //记录相关变化,使得控件完全画出界面就删除
        int result = viewHolder.itemView.getBottom();
        float res = result+dY;
        int index = viewHolder.getAdapterPosition();
//        Log.d(TAG, "onChildDraw:Result " + res);
//        Log.d(TAG, "onChildDraw:Position " + viewHolder.getAdapterPosition());
        if (res < 0){
            if (up){	//这里的up必须有,否则删除了当前item一会,因为还在滑动,会返回index为-1
                mListener.onItemDelete(index);
                up = false;
            }
//            Log.d(TAG, "onChildDraw: "+index);
        }
        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
    }
    @Override
    public long getAnimationDuration(RecyclerView recyclerView, int animationType, float animateDx, float animateDy) {
        //手指放开
        up = true;
        return super.getAnimationDuration(recyclerView, animationType, animateDx, animateDy);
    }
}

这里是适配器和itemTouchHelper的接口

下面的接口都在adapter中实现,然后itemTouchHelper中使用,完成解耦。

public interface MyItemTouchHelperListener {
    /**
     * 监听拖拽事件
     * itemMovie
     */
    void onItemMove(int fromPosition,int toPosition);
    /**
     * 监听删除事件
     * itemDelete
     */
    void onItemDelete(int position);
    /**
     * 被选中的时候
     */
    void onSelectedItem(RecyclerView.ViewHolder viewHolder);
    /**
     * UP的时候,手指已经离开
     */
    void onSelectedFinish(RecyclerView.ViewHolder viewHolder);
}

这里是Adapter的实现

这里的mData自定义的序列化实现,直接使用string更方便。当然我也放出来对应的bean。

public class MyItemTouchHelperAdapter extends  RecyclerView.Adapter<MyItemTouchHelperAdapter.ItemViewHolder>  implements MyItemTouchHelperListener {
    private ArrayList<ItemData> mData;
    private Context mContext;
    private OnItemClickListener mOnItemClickListener;

    public MyItemTouchHelperAdapter(Context mContext,ArrayList<ItemData> mData){
        this.mData = mData;
        this.mContext = mContext;
    }

    class ItemViewHolder extends RecyclerView.ViewHolder{
        TextView textView;
        ImageView imageView;
        public ItemViewHolder(@NonNull View itemView) {
            super(itemView);
            textView = itemView.findViewById(R.id.tv_item_recyclerView);
            imageView = itemView.findViewById(R.id.iv_item_recyclerView);
        }
    }

    /**
     * 监听拖拽实现
     * listener的接口实现
     * @param fromPosition
     * @param toPosition
     */
    @Override
    public void onItemMove(int fromPosition, int toPosition) {
        if (fromPosition < toPosition) {
            for (int i = fromPosition; i < toPosition; i++) {
                Collections.swap(mData, i, i + 1);
            }
        } else {
            for (int i = fromPosition; i > toPosition; i--) {
                Collections.swap(mData, i, i - 1);
            }
        }
        updateDataHome();
        notifyItemMoved(fromPosition,toPosition);
    }

    /**
     * 监听拖拽删除实现
     * listener的接口实现
     * @param position
     */
    @Override
    public void onItemDelete(int position) {
        ItemData item = mData.get(position);
        mData.remove(position);
        notifyItemRemoved(position);
        notifyDataSetChanged();
        updateDataHome();
        updateDataMore(item);
    }

    /**
     * 持久化
     */
    private void updateDataHome(){
        ACache.get(mContext).put("itemsHome",mData);
    }

    private void updateDataMore(ItemData itemData){
        ArrayList<ItemData> hideData = (ArrayList<ItemData>) ACache.get(mContext).getAsObject("itemsMore");
        hideData.add(itemData);
        ACache.get(mContext).put("itemsMore",hideData);
    }

    /**
     * 选中实现
     * @param viewHolder
     */
    @Override
    public void onSelectedItem(RecyclerView.ViewHolder viewHolder) {
        //获取系统震动服务
        Vibrator vibrator = (Vibrator) mContext.getSystemService(Service.VIBRATOR_SERVICE);
        vibrator.vibrate(70);
        viewHolder.itemView.setBackgroundColor(Color.LTGRAY);
    }

    /**
     * 选中结束实现
     * @param viewHolder
     */
    @Override
    public void onSelectedFinish(RecyclerView.ViewHolder viewHolder) {
        viewHolder.itemView.setBackgroundColor(Color.TRANSPARENT);
    }

    @NonNull
    @Override
    public ItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recyclerview,parent,false);
        ItemViewHolder viewHolder = new ItemViewHolder(view);
        viewHolder.itemView.setOnClickListener(view1 -> {
            if (mOnItemClickListener != null) {
                mOnItemClickListener.onItemClick(view1, viewHolder.getAdapterPosition());
            }
        });
        /**
         * 这里是图片自适应宽度
         *
         */
        Resources resources = mContext.getResources();
        DisplayMetrics dm = resources.getDisplayMetrics();
        int width = dm.widthPixels;
        int height = dm.heightPixels;
        int myWidth = (width - 6*2 - 3)/3;
        view.getLayoutParams().width = myWidth;
        return viewHolder ;
    }


    @Override
    public void onBindViewHolder(@NonNull ItemViewHolder holder, int position) {
        holder.textView.setText(mData.get(position).getResId());
        holder.imageView.setBackgroundResource(mData.get(position).getBitmap());

    }

    @Override
    public int getItemCount() {
        return mData != null ? mData.size() : 0;
    }

    /**
     * 监听接口,给与mainActivity实现
     * @param mOnItemClickListener
     */
    public void setOnItemClickListener(OnItemClickListener mOnItemClickListener){
        this.mOnItemClickListener = mOnItemClickListener;
    }
    public interface  OnItemClickListener{
        void onItemClick(View view,int position);
    }

}

这是对应的recyclerView的xml文件和bean文件。

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/iv_item_recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

    <TextView
        android:id="@+id/tv_item_recyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:layout_gravity="bottom"
        android:layout_marginBottom="20dp"
        android:text="测试"

        />
</FrameLayout>
public class ItemData implements Serializable {
    private int resId;

    private int bitmap; //background

    private Bitmap itemImgBitmap; //itemImage


    public ItemData(int resId, int bitmap) {
        this.resId = resId;
        this.bitmap = bitmap;
    }

    public ItemData(int resId, int bitmap, Bitmap itemImgBitmap) {
        this.resId = resId;
        this.bitmap = bitmap;
        this.itemImgBitmap = itemImgBitmap;
    }

    public int getResId() {
        return resId;
    }

    public void setResId(int resId) {
        this.resId = resId;
    }

    public int getBitmap() {
        return bitmap;
    }

    public void setBitmap(int bitmap) {
        this.bitmap = bitmap;
    }

    public Bitmap getItemImgBitmap() {
        return itemImgBitmap;
    }

    public void setItemImgBitmap(Bitmap itemImgBitmap) {
        this.itemImgBitmap = itemImgBitmap;
    }
}

间隔

下面就应该根据业务需求实现分页功能和间隔的设置。

首先因为业务需求,我这里是网格布局的,所以加载布局管理器,GridLayoutManager并且实现横向滚动。

然后怎么实现间隔呢,这个第一反应肯定是recyclerView.addItemDecoration,没错使用这个一点毛病都没有,所以使用这个,然后自定义一下间隔。代码如下:

public class SpaceItemDecoration extends RecyclerView.ItemDecoration {

    Context mContext;
    float space;
    public SpaceItemDecoration(Context mContext,float space) {
        this.space = space;
        this.mContext = mContext;
    }

    @Override
    public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
        super.getItemOffsets(outRect,view,parent,state);
        int item = parent.getChildAdapterPosition(view) %6;
        int spacing =  DimensionConvert.dip2px(mContext,space);
        switch (item){
            case 0:
                outRect.left = DimensionConvert.dip2px(mContext,3);
                outRect.top = spacing;
                outRect.bottom = (spacing / 2);
                break;
            case 2:
            case 4:
                outRect.top = spacing;
                outRect.left = spacing;
//                outRect.right = DimensionConvert.dip2px(mContext,3);
                outRect.bottom = (spacing / 2);
                break;
            case 1:
                outRect.left = DimensionConvert.dip2px(mContext,3);
//                outRect.bottom =  spacing;
                outRect.top =  (spacing / 2);
                break;
            case 3:
            case 5:
                outRect.top =  (spacing / 2);
                outRect.left =  spacing;
//                outRect.right = DimensionConvert.dip2px(mContext,3);
//                outRect.bottom =  spacing;
                break;
        }
    }
}

对了,这里涉及一个px和dp之间的转换,工具文件如下,当然不转化直接使用也是没毛病的。

import android.content.Context;

/**
 * Created by shichaohui on 2015/7/10 0010.
 */
public class DimensionConvert {

    /**
     * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
     *
     * @param context
     * @param dpValue 要转换的dp值
     */
    public static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    /**
     * 根据手机的分辨率从 px(像素) 的单位 转成为 dp
     *
     * @param context
     * @param pxValue 要转换的px值
     */
    public static int px2dip(Context context, float pxValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }
}

分页

要实现分页效果的话,其实Android官方给我们提供了SnapHelper这个辅助类的,有兴趣的可以去了解一下,但是它不符合我的业务需求啊,因为我要完成类似分页效果,官方提供的PagerSnapHelper我这里可能因为是横向滚动的缘故,一次就能一列,但是我要三列,完成类似分页的效果,所以只能自己来实现了。具体代码如下:

import android.graphics.PointF;
import android.util.DisplayMetrics;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearSmoothScroller;
import androidx.recyclerview.widget.OrientationHelper;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.SnapHelper;


/**
 * Created by Muyuki on  2019/11/8
 * 网格布局分页效果
 * 仅限布局为GridLayoutManager使用
 */
public class GridPagerSnapHelper extends SnapHelper {
    @Nullable
    private OrientationHelper mVerticalHelper;
    @Nullable
    private OrientationHelper mHorizontalHelper;
    private RecyclerView recyclerView;
    private int rowCount = 1;
    private int columCount = 1;


    /**
     * @param row 行
     * @param column 列
     */
    public GridPagerSnapHelper(int row,int column) {
        this.rowCount = row;
        this.columCount = column;

    }

    @Override
    public void attachToRecyclerView(@Nullable RecyclerView recyclerView) throws IllegalStateException {
        super.attachToRecyclerView(recyclerView);
        this.recyclerView = recyclerView;
    }

    @Nullable
    @Override
    public int[] calculateDistanceToFinalSnap(@NonNull RecyclerView.LayoutManager layoutManager, @NonNull View targetView) {
        int[] out = new int[2];
        if (layoutManager.canScrollHorizontally()) {
            out[0] = this.distanceToStart(layoutManager, targetView, this.getHorizontalHelper(layoutManager));
        } else {
            out[0] = 0;
        }

        if (layoutManager.canScrollVertically()) {
            out[1] = this.distanceToStart(layoutManager, targetView, this.getVerticalHelper(layoutManager));
        } else {
            out[1] = 0;
        }

        return out;
    }

    @Nullable
    @Override
    public View findSnapView(RecyclerView.LayoutManager layoutManager) {
        if (layoutManager.canScrollVertically()) {
            return this.findStartSnapView(layoutManager, this.getVerticalHelper(layoutManager));
        } else {
            return layoutManager.canScrollHorizontally() ? this.findStartSnapView(layoutManager, this.getHorizontalHelper(layoutManager)) : null;
        }
    }

    @Override
    public int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager, int velocityX, int velocityY) {
        int itemCount = layoutManager.getItemCount();
        if (itemCount == 0) {
            return -1;
        } else {
            View mStartMostChildView = null;
            if (layoutManager.canScrollVertically()) {
                mStartMostChildView = this.findStartView(layoutManager, this.getVerticalHelper(layoutManager));
            } else if (layoutManager.canScrollHorizontally()) {
                mStartMostChildView = this.findStartView(layoutManager, this.getHorizontalHelper(layoutManager));
            }

            if (mStartMostChildView == null) {
                return -1;
            } else {
                int centerPosition = layoutManager.getPosition(mStartMostChildView);
                if (centerPosition == -1) {
                    return -1;
                } else {

                    // 计算当前页面索引
                    int pagerIndex = centerPosition / (rowCount * columCount);
                    // 是否滑向下一页
                    boolean forwardDirection;
                    if (layoutManager.canScrollHorizontally()) {
                        forwardDirection = velocityX > 0;
                    } else {
                        forwardDirection = velocityY > 0;
                    }

                    // 条目是否是翻转模式
                    boolean reverseLayout = false;
                    if (layoutManager instanceof RecyclerView.SmoothScroller.ScrollVectorProvider) {
                        RecyclerView.SmoothScroller.ScrollVectorProvider vectorProvider = (RecyclerView.SmoothScroller.ScrollVectorProvider) layoutManager;
                        PointF vectorForEnd = vectorProvider.computeScrollVectorForPosition(itemCount - 1);
                        if (vectorForEnd != null) {
                            reverseLayout = vectorForEnd.x < 0.0F || vectorForEnd.y < 0.0F;
                        }
                    }
                    int targetPosition = -1;
                    if (reverseLayout) {
                        targetPosition = (forwardDirection ? (pagerIndex - 1) * (rowCount * columCount) : (pagerIndex) * (rowCount * columCount));
                    } else {
                        targetPosition = (forwardDirection ? (pagerIndex + 1) * (rowCount * columCount) : (pagerIndex) * (rowCount * columCount));
                    }
                    return targetPosition;
                }
            }
        }
    }

    @Override
    protected LinearSmoothScroller createSnapScroller(RecyclerView.LayoutManager layoutManager) {
        return !(layoutManager instanceof RecyclerView.SmoothScroller.ScrollVectorProvider) ? null : new LinearSmoothScroller(this.recyclerView.getContext()) {
            protected void onTargetFound(View targetView, RecyclerView.State state, Action action) {
                int[] snapDistances = GridPagerSnapHelper.this.calculateDistanceToFinalSnap(GridPagerSnapHelper.this.recyclerView.getLayoutManager(), targetView);
                int dx = snapDistances[0];
                int dy = snapDistances[1];
                int time = this.calculateTimeForDeceleration(Math.max(Math.abs(dx), Math.abs(dy)));
                if (time > 0) {
                    action.update(dx, dy, time, this.mDecelerateInterpolator);
                }

            }

            protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
                return 100.0F / (float) displayMetrics.densityDpi;
            }

            protected int calculateTimeForScrolling(int dx) {
                return Math.min(100, super.calculateTimeForScrolling(dx));
            }
        };
    }

    private int distanceToStart(@NonNull RecyclerView.LayoutManager layoutManager, @NonNull View targetView, OrientationHelper helper) {
        int childStart = helper.getDecoratedStart(targetView);
        int containerStart;
        if (layoutManager.getClipToPadding()) {
            containerStart = helper.getStartAfterPadding();
        } else {
            containerStart = 0;
        }

        return childStart - containerStart;
    }

    @Nullable
    private View findStartSnapView(RecyclerView.LayoutManager layoutManager, OrientationHelper helper) {
        int childCount = layoutManager.getChildCount();
        if (childCount == 0) {
            return null;
        } else {
            View closestChild = null;
            int start;
            if (layoutManager.getClipToPadding()) {
                start = helper.getStartAfterPadding();
            } else {
                start = 0;
            }

            int absClosest = 2147483647;

            for (int i = 0; i < childCount; ++i) {
                View child = layoutManager.getChildAt(i);
                int childStart = helper.getDecoratedStart(child);
                int absDistance = Math.abs(childStart - start);
                if (absDistance < absClosest) {
                    absClosest = absDistance;
                    closestChild = child;
                }
            }

            return closestChild;
        }
    }

    @Nullable
    private View findStartView(RecyclerView.LayoutManager layoutManager, OrientationHelper helper) {
        int childCount = layoutManager.getChildCount();
        if (childCount == 0) {
            return null;
        } else {
            View closestChild = null;
            int startest = 2147483647;

            for (int i = 0; i < childCount; ++i) {
                View child = layoutManager.getChildAt(i);
                int childStart = helper.getDecoratedStart(child);
                if (childStart < startest) {
                    startest = childStart;
                    closestChild = child;
                }
            }

            return closestChild;
        }
    }

    @NonNull
    private OrientationHelper getVerticalHelper(@NonNull RecyclerView.LayoutManager layoutManager) {
        if (this.mVerticalHelper == null || this.mVerticalHelper.getLayoutManager() != layoutManager) {
            this.mVerticalHelper = OrientationHelper.createVerticalHelper(layoutManager);
        }

        return this.mVerticalHelper;
    }

    @NonNull
    private OrientationHelper getHorizontalHelper(@NonNull RecyclerView.LayoutManager layoutManager) {
        if (this.mHorizontalHelper == null || this.mHorizontalHelper.getLayoutManager() != layoutManager) {
            this.mHorizontalHelper = OrientationHelper.createHorizontalHelper(layoutManager);
        }

        return this.mHorizontalHelper;
    }
}

持久化

持久化的可以去看我上篇的实现一的最后面,可以看到ACache这个Android的轻量级持久化。

实现:MainActivity

public class MainActivity extends AppCompatActivity {
    private boolean isFirst;
    private static final String TAG = "MainActivity";
    private MyItemTouchHelperAdapter myItemTouchHelperAdapter;
    RecyclerView recyclerView;
    ArrayList<ItemData> mData;
    private ACache aCache;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG, "onCreate: 周期");
        isFirst = true;
        init();

    }
    private void init(){
        initData();

        recyclerView = findViewById(R.id.main_recyclerView);
        //设置网格布局
        GridLayoutManager manager = new GridLayoutManager(this,2, LinearLayoutManager.HORIZONTAL,false);
        recyclerView.setLayoutManager(manager);
        //设置间隔
        recyclerView.addItemDecoration(new SpaceItemDecoration(this,6));
        //设置翻页效果
        new GridPagerSnapHelper(2,3).attachToRecyclerView(recyclerView);
        //实现拖拽效果
        myItemTouchHelperAdapter = new MyItemTouchHelperAdapter(this,mData);
        MyItemTouchHelperCallback myItemTouchHelperCallback = new MyItemTouchHelperCallback(myItemTouchHelperAdapter);
        ItemTouchHelper itemTouchHelper = new ItemTouchHelper(myItemTouchHelperCallback);
        itemTouchHelper.attachToRecyclerView(recyclerView);
        recyclerView.setAdapter(myItemTouchHelperAdapter);
        //设置监听
        myItemTouchHelperAdapter.setOnItemClickListener(new MyItemTouchHelperAdapter.OnItemClickListener() {
            // 如果需要自定义点击时间间隔,自行传入毫秒值即可
            // @SingleClick(2000)
            @SingleClick(2000)
            @Override
            public void onItemClick(View view, int position) {
                switch (mData.get(position).getResId()) {
                    case R.string.version_more:
                        Intent intent = new Intent(MainActivity.this, GetMoreActivity.class);
                        MainActivity.this.startActivity(intent);
                        break;
                    case R.string.trans_order_pay_new:
                        Log.d(TAG, "onItemClick: ");
                        break;
                }
            }
        });

    }

    private void addSource(int resId, int bitmapId){
        if (resId ==0 || bitmapId ==0)
            return;
        mData.add(new ItemData(resId,bitmapId));
    }
    //模拟数据
    private void initData(){
        aCache = ACache.get(MainActivity.this);
        if (aCache.getAsObject("itemsHome") != null){
            mData = (ArrayList<ItemData>) aCache.getAsObject("itemsHome");
        }
        else {
            mData = new ArrayList<>();
            addSource(R.string.trans_order_pay_new, R.drawable.item_ordernew);
            addSource(R.string.trans_ant_credit_pay, R.drawable.item_antcredit);
            addSource(R.string.qrcode_trans, R.drawable.item_qrcode_trade);
            addSource(R.string.trans_membersale, R.drawable.item_membersale);
            addSource(R.string.trans_sale, R.drawable.item_sale);
            addSource(R.string.trans_auth, R.drawable.item_auth);
            addSource(R.string.trans_orderrefund, R.drawable.order_refund_icon);
            addSource(R.string.trans_sale_void, R.drawable.item_void);
            addSource(R.string.trans_refund, R.drawable.item_refund);
            addSource(R.string.trans_login, R.drawable.item_login);
            addSource(R.string.trans_query, R.drawable.item_quey_money);
            addSource(R.string.trans_detail, R.drawable.item_detail);
            addSource(R.string.trans_print, R.drawable.item_print);
            addSource(R.string.logout_settle, R.drawable.item_settle);
            addSource(R.string.trans_cashout, R.drawable.item_cash_out);
            addSource(R.string.lock_terminal, R.drawable.item_lock);
            addSource(R.string.version_info, R.drawable.item_version);
            addSource(R.string.version_more, R.drawable.item_version);

            if (mData != null){
                aCache.put("itemsHome",mData,30 * ACache.TIME_DAY);
                Log.d(TAG, "initData: "+mData);
            }
        
            Log.d(TAG, "initData: 进入没有");
        }
        if (mData.size() %6 != 0){
            int num = mData.size() % 6 ;
            for (int i = 0; i < num; i++) {
                    addSource(R.string.item_forhome,R.drawable.item_forhome);
            }
        }

    }

    @Override
    protected void onResume(){
        if (!isFirst){
            initData();
            myItemTouchHelperAdapter.notifyDataSetChanged();
        }
        super.onResume();
        Log.d(TAG, "onResume:周期 ");
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.d(TAG, "onStart: 周期");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG, "onStop: 周期");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy: 周期");
    }

    @Override
    protected void onPause() {
        isFirst = false;
//        init();
        super.onPause();
        Log.d(TAG, "onPause: 周期");
    }

}

最后还有一个点击仿重,这里使用的是AOP来解决重复点击问题,具体博客参考如下:

AOP解决按钮仿重:www.jianshu.com/p/ee2bddca1…

横向分页:blog.csdn.net/mr_lichao/a…

到此为止也就结束了,那么拜拜了,记录自己的学习,也与各位大佬们分享自己的学习。