一行代码实现Recycleview拖拽排序

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014736095/article/details/89378858

公司的老项目需要加一个拖拽排序的功能,以前是用listview来实现的,自定义listview,然后再onInterceptTouchEvent中拦截DOWN的事件生成一个新的View,达到一个拖动的效果。这个思想是没有毛病,就是太繁琐了。Recycleview的效果就非常好,最后简单封装了一下,给大家使用:

 首先我们需要一个工具类:DragRecycleViewHelper 


import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;


import java.util.Collections;
import java.util.List;

/**
 * 拖拽工具类,简单的上下拖拽可以直接使用{@link AbstrDragRecycleViewCallback}
 * 默认为长按拖拽,如需触摸拖拽,触摸事件中调用{@link DragRecycleViewHelper#startDrag}即可
 * Created by Gavin on 2019/4/17.
 */

public class DragRecycleViewHelper extends ItemTouchHelper {

    /**
     * Creates an ItemTouchHelper that will work with the given Callback.
     * <p>
     * You can attach ItemTouchHelper to a RecyclerView via
     * {@link #attachToRecyclerView(RecyclerView)}. Upon attaching, it will add an item decoration,
     * an onItemTouchListener and a Child attach / detach listener to the RecyclerView.
     *
     * @param callback The Callback which controls the behavior of this touch helper.
     */
    private DragRecycleViewHelper(Callback callback) {
        super(callback);
    }

    public DragRecycleViewHelper(RecyclerView recyclerView, ItemTouchHelper.Callback callback) {
        super(callback);
        attachToRecyclerView(recyclerView);
    }

    public abstract static class AbstrDragRecycleViewCallback extends ItemTouchHelper.Callback {
        /**
         * recycleview的adapter的数据源
         */
        private List listData;
        /**
         * recycleview的headerview数量
         */
        private final int HEADER_COUNT;

        /**
         * 拖拽监听
         * @param listData adapter的数据源
         * @param headerCount headerView条数
         */
        public AbstrDragRecycleViewCallback(List listData,int headerCount) {
            this.listData = listData;
            this.HEADER_COUNT = headerCount;
        }

        @Override
        public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
            int dragFlag = ItemTouchHelper.UP|ItemTouchHelper.DOWN;
            if (isLimitDragItem(viewHolder,viewHolder.getAdapterPosition())) {
                dragFlag = 0;
            }
            return makeMovementFlags(dragFlag,0);
        }

        @Override
        public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
            if (isLimitSwap(viewHolder,target)) {
                return false;
            }else{
                int fromIndex = viewHolder.getAdapterPosition();
                int toIndex = target.getAdapterPosition();
                if (fromIndex < toIndex) {
                    for (int i = fromIndex-1; i < toIndex- HEADER_COUNT; i++) {
                        Collections.swap(listData,i,i+ HEADER_COUNT);
                    }
                }else{
                    for (int i = fromIndex-1; i > toIndex- HEADER_COUNT; i--) {
                        Collections.swap(listData,i,i- HEADER_COUNT);
                    }
                }
                recyclerView.getAdapter().notifyItemMoved(fromIndex,toIndex);
            }

            return true;
        }

        @Override
        public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {

        }

        @Override
        public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
            super.onSelectedChanged(viewHolder, actionState);
            onDragItemStart(viewHolder, actionState);
        }

        @Override
        public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
            super.clearView(recyclerView, viewHolder);
            onDragItemFinish(viewHolder);
        }



        /**
         * 该条viewholder是否被禁止被拖动,默认为长按拖拽,如需触摸拖拽,触摸事件中调用{@link DragRecycleViewHelper#startDrag}即可
         * @param viewHolder
         * @param holderPosition
         * @return
         */
        protected abstract boolean isLimitDragItem(RecyclerView.ViewHolder viewHolder, int holderPosition);

        /**
         * 是否禁止被交换,如果第1,2条不被交换,这里应该返回target.getAdapterPosition() < 2
         * @param viewHolder
         * @param targetViewHolder
         * @return
         */
        protected abstract boolean isLimitSwap(RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder targetViewHolder);

        /**
         * 拖动开始后触发
         * @param viewHolder
         * @param actionState
         */
        protected  void onDragItemStart(RecyclerView.ViewHolder viewHolder, int actionState){};


        /**
         * 拖动结束后触发
         * 无须调用adapter.notifyDataSetChanged()了,已经被封装在父类了,直接写需要执行的逻辑即可。如保存操作
         *
         * @param viewHolder
         */
        protected abstract void onDragItemFinish(RecyclerView.ViewHolder viewHolder);
    }

}

 

 使用例子:


//...
//mIndicatorSettingRv 你的RecyclerView
//mList 你的数据源
//headerViewCount 你的RecyclerView是否有headerView,如果有的话这里写headerView的数量,没有写0
DragRecycleViewHelper itemTouchHelper = new DragRecycleViewHelper(mIndicatorSettingRv, new DragRecycleViewHelper.AbstrDragRecycleViewCallback(mList, headerViewCount) {
			@Override
			protected boolean isLimitDragItem(RecyclerView.ViewHolder viewHolder, int holderPosition) {
				return viewHolder.getAdapterPosition() < 2;
			}
			@Override
			protected boolean isLimitSwap(RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder targetViewHolder) {
				return targetViewHolder.getAdapterPosition() < 2;
			}

			@Override
			protected void onDragItemFinish(RecyclerView.ViewHolder viewHolder) {
				mIndicatorSettingAdapter.notifyDataSetChanged();
				saveHqSetting(6);
			}
		});
//...

猜你喜欢

转载自blog.csdn.net/u014736095/article/details/89378858
今日推荐