美文网首页代码
ItemTouchHelper.Callback实现仿朋友圈发布

ItemTouchHelper.Callback实现仿朋友圈发布

作者: 安与我 | 来源:发表于2019-04-15 16:16 被阅读0次

项目需求需要类似发布朋友圈拖拽排序的功能,故此记录一下,感谢Android SDK的强大。

API链接:https://developer.android.com/reference/android/support/v7/widget/helper/ItemTouchHelper.Callback

效果视频连接:https://blog.csdn.net/CCstar1/article/details/89284445

网上有很多使用GirdView实现拖拽排序效果相对来说比较复杂,在保证效率和质量的情况下我这里选择使用RecycleView,官方提供了TiemTouchHelper来支持此效果的完成,它的出现本意是上下拖拽实现排序,左右拖拽实现删除(此处非瀑布流)。但是实现拖拽效果已经绰绰有余了。下面我们开始吧。

TiemTouchHelper:(官方解释)

此类是ItemTouchHelper与您的应用程序之间的契约。它允许您控制每个ViewHolder启用触摸行为,并在用户执行这些操作时接收回调。

要控制用户可以对每个视图执行哪些操作,您应该覆盖 getMovementFlags(RecyclerView, ViewHolder)并返回适当的方向标志集。(LEFT,RIGHT,START,END, UP,DOWN)。您可以使用 makeMovementFlags(int, int)它轻松构建它。或者,您可以使用 ItemTouchHelper.SimpleCallback。

如果用户拖动item,ItemTouchHelper将调用 onMove(recyclerView, dragged, target)。收到此回调后,您应该将项目从旧位置(dragged.getAdapterPosition())移动到target.getAdapterPosition()适配器中的新位置()并调用notifyItemMoved(int, int)。要控制可以删除视图的位置,您可以覆盖 canDropOver(RecyclerView, ViewHolder, ViewHolder)。当拖动视图与多个其他视图重叠时,Callback会选择最近的视图,拖动的视图可能会更改位置。虽然此方法适用于许多用例,但如果您有自定义LayoutManager,则可以覆盖 chooseDropTarget(ViewHolder, java.util.List, int, int)以选择自定义放置目标。

滑动视图时,ItemTouchHelper会对其进行动画处理,直到它超出范围,然后调用 onSwiped(ViewHolder, int)。此时,您应该更新适配器(例如删除item)并调用相关的Adapter#notify事件。

自定义了Recycleview实现拖拽,更换位置有数据换位置然后刷新实现并非Recycleview自己实现,代码如下:

public class DragItemRecyclerView extends RecyclerView {

    private ItemTouchHelper itemTouchHelper;

    private DragAdapter dragAdapter;

    private float ALPHA_FULL = 1.0f;

    public DragItemRecyclerView(Context context) {

        super(context);

    }

    public DragItemRecyclerView(Context context, @Nullable AttributeSet attrs) {

        super(context, attrs);

    }

    public DragItemRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {

        super(context, attrs, defStyle);

    }

    @Override

    public void setAdapter(Adapter adapter) {

        super.setAdapter(adapter);

        dragAdapter = (DragAdapter) adapter;

        init();

    }

    private void init() {

        this.getItemAnimator().setChangeDuration(0);

        if (itemTouchHelper == null) {

            itemTouchHelper = new ItemTouchHelper(new ItemTouchHelperCallback());

            itemTouchHelper.attachToRecyclerView(this);

        }

    }

    public class ItemTouchHelperCallback extends ItemTouchHelper.Callback {

        int endPosition, startPosition;

        @Override

        public int getMovementFlags(RecyclerView recyclerView, ViewHolder viewHolder) {

            if (dragAdapter.list != null && !TextUtils.isEmpty(dragAdapter.list.get(viewHolder.getAdapterPosition())) && dragAdapter.list.get(viewHolder.getAdapterPosition()).equals(CreateTopicActivity.ADD_IMAGE)) {

                return makeMovementFlags(0, 0);

            }

            if (dragAdapter.list != null && !TextUtils.isEmpty(dragAdapter.list.get(viewHolder.getAdapterPosition())) && !PhotoTools.isImageFile(dragAdapter.list.get(viewHolder.getAdapterPosition()))) {

                return makeMovementFlags(0, 0);

            }

            if (recyclerView.getLayoutManager() instanceof GridLayoutManager || recyclerView.getLayoutManager() instanceof StaggeredGridLayoutManager) {

                final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;

                //不需要滑动

                final int swipeFlags = 0;

                return makeMovementFlags(dragFlags, swipeFlags);

            } else {

                final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;

                final int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;

                return makeMovementFlags(dragFlags, swipeFlags);

            }

        }

        @Override

        public boolean onMove(RecyclerView recyclerView, ViewHolder viewHolder, ViewHolder target) {

            if (viewHolder.getItemViewType() != target.getItemViewType()) {

                return false;

            }

            startPosition = viewHolder.getAdapterPosition();

            endPosition = target.getAdapterPosition();

            return dragAdapter.onItemMove(startPosition, endPosition);

        }

        @Override

        public void clearView(@NonNull RecyclerView recyclerView, @NonNull ViewHolder viewHolder) {

            super.clearView(recyclerView, viewHolder);

            if (dragAdapter != null) {

                dragAdapter.notifyItemRangeChanged(Math.min(startPosition, endPosition), Math.abs(startPosition - endPosition) + 1);

            }

        }

        @Override

        public boolean canDropOver(RecyclerView recyclerView, ViewHolder current, ViewHolder target) {

            return true;

        }

        @Override

        public void onSwiped(ViewHolder viewHolder, int direction) {

        }

        @Override

        public boolean isLongPressDragEnabled() {

            return true;

        }

        @Override

        public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {

            if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {

                //自定义滑动动画

                final float alpha = ALPHA_FULL - Math.abs(dX) / (float) viewHolder.itemView.getWidth();

                viewHolder.itemView.setAlpha(alpha);

                viewHolder.itemView.setTranslationX(dX);

            } else {

                super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);

            }

        }

    }

    public interface ItemTouchHelperAdapter {

        //数据交换

        boolean onItemMove(int fromPosition, int toPosition);

    }

}

adapter相关代码,主要是onMore调起在adapter内方法,根据返回更换位置item的position更换数据位置然后notify,代码如下:

    @Override

    public boolean onItemMove(int fromPosition, int toPosition) {

        if (list.get(toPosition).equals(CreateTopicActivity.ADD_IMAGE))

            return false;

        if (!PhotoTools.isImageFile(list.get(toPosition)))

            return false;

        //交换位置

        Collections.swap(list, fromPosition, toPosition);

        notifyItemMoved(fromPosition, toPosition);

        return true;

    }

上述第一个if是判断是不是添加按钮,如果是不更换,需求默认添加按钮在最后。第二个if判断是否是视频,视频需求默认第一位也不可更换位置。

大家没有看错就这点代码实现了所有功能,如果大家还有什么问题欢迎留言。

相关文章

网友评论

    本文标题:ItemTouchHelper.Callback实现仿朋友圈发布

    本文链接:https://www.haomeiwen.com/subject/lvbuwqtx.html