欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2022-03-03 21:57:25
实现拖拽效果二: 使用RecyclerView + ItemTouchHelper 实现拖拽、删除,滑动删除效果因为demo适配了公司的业务,具体图层不好放出来,难受。但是这毕竟只是记录学习,自己知道实现了就好!之前是使用GridView实现的拖拽效果,但是其实他存在一个问题,当时涉及我本身的业务,所以使用那个很难实现,所以发现了这个。GridView如果要实现横向滚动实现分页功能,并且支持拖拽互换就存在很大的问题,当然不同的trager也是可以实现的,但是很不方便,然后使用ItemTouchHelp...

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

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

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

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

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

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

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

解耦

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

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

从上往下分别是

  • 实现分页效果的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解决按钮仿重:https://www.jianshu.com/p/ee2bddca1975

横向分页:https://blog.csdn.net/mr_lichao/article/details/102968888

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

本文地址:https://blog.csdn.net/weixin_43900919/article/details/108705258

相关标签: android