Android RecyclerView通过ItemTouchHelper拖拽重排后item位置未更新问题
问题根因
你遇到的拖拽后位置显示不更新的问题,核心有两个错误点:
onMove方法返回值错误:你当前返回false,ItemTouchHelper会判定本次移动操作未被处理,不会完成后续的位置同步流程。- 仅调用
notifyItemMoved只会触发移动动画,不会刷新受影响区间内item的绑定数据:你按钮上显示的位置是bindViewHolder时赋值的旧值,移动后没有重新绑定所以显示不变。
解决方案
- 修正
onMove返回值为true - 移动后刷新受影响的item区间,让所有位置变动的item重新绑定数据,显示最新位置
- 要获取item最新位置时,在
onBindViewHolder中使用传入的position参数,或者任意场景下调用ViewHolder.getAdapterPosition()方法即可拿到实时位置。
修改后代码示例
ItemTouchHelper.SimpleCallback simpleCallback = new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.START | ItemTouchHelper.END , 0) { @Override public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) { int fromPosition = viewHolder.getAdapterPosition(); int toPosition = target.getAdapterPosition(); // 交换数据源 Collections.swap(datalist,fromPosition,toPosition); // 通知item移动 recyclerView.getAdapter().notifyItemMoved(fromPosition,toPosition); // 刷新受影响的区间,更新item上显示的位置信息 int min = Math.min(fromPosition, toPosition); int max = Math.max(fromPosition, toPosition); recyclerView.getAdapter().notifyItemRangeChanged(min, max - min + 1); // 处理了移动事件返回true return true; } @Override public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { } // 可选:如果需要在拖拽结束时获取最终位置,重写这个方法 @Override public void onSelectedChanged(@Nullable RecyclerView.ViewHolder viewHolder, int actionState) { super.onSelectedChanged(viewHolder, actionState); if (actionState == ItemTouchHelper.ACTION_STATE_IDLE && viewHolder != null) { // 此时获取的就是拖拽结束后item的最终位置 int finalPosition = viewHolder.getAdapterPosition(); } } };
Adapter绑定逻辑示例
在onBindViewHolder中直接使用方法传入的position参数即可获取最新位置:
@Override public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { // 直接用这个position就是最新位置 holder.button.setText("按钮" + position); // 也可以把位置存到按钮的tag里,后续点击时直接取 holder.button.setTag(position); }
内容的提问来源于stack exchange,提问作者Priyanshu Pundhir
相关产品推荐
相关产品推荐

