ItemTouchHelper.Callback实现仿朋友圈发布图片拖拽排序

项目需求需要类似发布朋友圈拖拽排序的功能,故此记录一下,感谢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判断是否是视频,视频需求默认第一位也不可更换位置。

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • 家里兄弟姐妹比较多,父亲早逝,留下母亲一个人处理大家庭矛盾,处理方向是和平,事实上却有很多无法平息的涌动。父亲与母...
    寂灭Ganesha泳卉阅读 482评论 0 0
  • Dubbo入门-协议&注册中心 一、配置dubbo多协议模式 1、默认协议 Dubbo缺省协议采用单一长连接和NI...
    Java帮帮阅读 1,167评论 1 4
  • 江山如画,凭谁记,眸底深处伊人笑。 繁花似锦,烟波碎,桃花落尽人已非。 而今,一缕轻愁,任凭江山无限,与谁共。 断...
    雨晴烟晚断阅读 632评论 0 0
  • 嵊县板川访赠贤弟明亮 黄磊/文 越秀灵毓鼎奇殊,板川鹤立赛名厨。 青山送吾至剡溪,圣水为鸣鼓与呼。 洁身守立去百污...
    黄磊的简书阅读 275评论 0 5