一行代码实现Recycleview拖拽排序

公司的老项目需要加一个拖拽排序的功能,以前是用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);
			}
		});
//...

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的实现自定义RecycleView Gallery的示例代码。这个示例代码使用了自定义的LayoutManager和自定义的View实现画廊效果。 首先,我们创建一个自定义的LayoutManager,名为GalleryLayoutManager: ```java public class GalleryLayoutManager extends LinearLayoutManager { private float mScale = 0.8f; // 缩放比例 public GalleryLayoutManager(Context context, int orientation, boolean reverseLayout) { super(context, orientation, reverseLayout); } @Override public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) { int scrolled = super.scrollHorizontallyBy(dx, recycler, state); float midpoint = getWidth() / 2.0f; float d0 = 0.0f; float d1 = mScale; float s0 = 1.0f; float s1 = mScale; for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); float childMidpoint = (getDecoratedRight(child) + getDecoratedLeft(child)) / 2.0f; float d = Math.min(d1, Math.abs(midpoint - childMidpoint) / getWidth()); float scale = s0 + (s1 - s0) * (1.0f - d); child.setScaleX(scale); child.setScaleY(scale); } return scrolled; } } ``` 这个LayoutManager会在RecyclerView中创建一个水平滚动的画廊效果,并且会根据RecyclerView的滚动位置来动态调整每个子项的缩放比例,实现画廊效果。 然后,我们创建一个自定义的View,名为GalleryItemView: ```java public class GalleryItemView extends FrameLayout { private ImageView mImageView; public GalleryItemView(Context context) { super(context); init(); } public GalleryItemView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public GalleryItemView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { LayoutInflater.from(getContext()).inflate(R.layout.view_gallery_item, this, true); mImageView = findViewById(R.id.image); } public void setImage(int resId) { mImageView.setImageResource(resId); } } ``` 这个View会在RecyclerView中的每个子项中显示一个图片,并且会根据LayoutManager的要求来动态调整自己的缩放比例。 最后,我们创建一个RecyclerView,并设置它的LayoutManager和Adapter: ```java public class GalleryActivity extends AppCompatActivity { private static final int[] IMAGES = { R.drawable.image1, R.drawable.image2, R.drawable.image3, R.drawable.image4, R.drawable.image5, R.drawable.image6, R.drawable.image7, R.drawable.image8, R.drawable.image9, R.drawable.image10, }; private RecyclerView mRecyclerView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_gallery); mRecyclerView = findViewById(R.id.recycler_view); mRecyclerView.setLayoutManager(new GalleryLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)); mRecyclerView.setAdapter(new Adapter()); } private class Adapter extends RecyclerView.Adapter<ViewHolder> { @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { GalleryItemView itemView = new GalleryItemView(parent.getContext()); itemView.setLayoutParams(new RecyclerView.LayoutParams(300, 300)); return new ViewHolder(itemView); } @Override public void onBindViewHolder(ViewHolder holder, int position) { ((GalleryItemView) holder.itemView).setImage(IMAGES[position % IMAGES.length]); } @Override public int getItemCount() { return 100; } } private static class ViewHolder extends RecyclerView.ViewHolder { public ViewHolder(View itemView) { super(itemView); } } } ``` 这个示例代码会在RecyclerView中显示100个随机的图片,并且会以画廊的形式展示出来。 希望这个示例代码能够对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值