Перетаскивание RecyclerView не работает с несколькими типами представлений

Я пытаюсь использовать RecyclerView с вертикальным LinearLayoutManager для отображения элементов списка. Этот список может содержать несколько различных типов элементов (различные макеты), и он может быть переупорядочен пользователем с помощью перетаскивания.

Для типов элементов, как описано в документации Android, я переопределил метод getItemType, чтобы обрабатывать различные типы представлений в утилите и обрабатывать их в onCreateViewHolder и onBindViewHolder. Это работает как шарм.

Для изменения порядка перетаскивания я использовал ItemTouchHelper.Callback (вдохновленный этим примером проекта). Это тоже хорошо работает.

Проблема возникает, когда я пытаюсь использовать разные типы элементов и поведение перетаскивания. Пока перетаскивание происходит между элементами одного типа, это работает хорошо, но когда я перетаскиваю представление типа A поверх представления типа B, остановка перетаскивания и представление возвращаются в исходное положение.

Вот мой код:

MyFragment.java

public class MyFragment extends Fragment implements MyAdapter.Listener {

private MyViewModel mViewModel;
private RecyclerView mRecyclerView;
private MyAdapter mAdapter;
private ItemTouchHelper mItemTouchHelper;

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View root = inflater.inflate(R.layout.fragment, container, false);
    mRecyclerView = root.findViewById(R.id.recyclerView);

    mAdapter = new MyAdapter(this);
    mRecyclerView.setAdapter(mAdapter);
    mItemTouchHelper = new ItemTouchHelper(new MyDragHelperCallback(mAdapter));
    mItemTouchHelper.attachToRecyclerView(mRecyclerView);


    mViewModel = ViewModelProviders.of(getActivity()).get(MyViewModel.class);
    mViewModel.addObserver(this, new Observer<List<Item>>() {
        @Override
        public void onChanged(@Nullable List<Item> items) {
            mAdapter.updateList(items);
        }
    });
    mAdapter.updateList(mViewModel.getList());

    return root;
}

@Override
public void onStartDragRequest(@NonNull RecyclerView.ViewHolder viewHolder) {
    mItemTouchHelper.startDrag(viewHolder);
}
}

MyDragHelperCallback.java

public class MyDragHelperCallback extends ItemTouchHelper.Callback {

private static final int DRAG_MOVEMENT_FLAGS = ItemTouchHelper.UP | ItemTouchHelper.DOWN;

@NonNull
private MyDragListener mListener;

public MyDragHelperCallback(@NonNull MyDragListener listener) {
    mListener = listener;
}

@Override
public boolean isLongPressDragEnabled() {
    return true;
}

@Override
public boolean isItemViewSwipeEnabled() {
    return false;
}

@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
    if (!(recyclerView.getLayoutManager() instanceof LinearLayoutManager)) {
        throw new IllegalArgumentException("Should only be used with a LinearLayoutManager");
    }

    return makeMovementFlags(DRAG_MOVEMENT_FLAGS, 0);
}

@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
    mListener.onItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
    return true;
}

@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
    // Nothing to do
}

}

MyDragListener.java

public interface MyDragListener {
    void onItemMoved(int from, int to);
}

MyAdapter.java

public class MyAdapter extends RecyclerView.Adapter<MyHolder> implements MyDragListener {

    @Nullable
    private List<Item> mList;

    public void updateList(@Nullable List<Item> list) {
        mList = list;
        notifyDataSetChanged();
    }

    @Override
    public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == 0) {
            return new MyHolderBis(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_bis, parent, false));
        }
        return new MyHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false));
    }

    @Override
    public void onBindViewHolder(final MyHolder holder, int position) {
        holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                mListener.onStartDragRequest(holder);
                return true;
            }
        });
        // bind views to data
    }

    @Override
    public int getItemCount() {
        return mList != null ? mList.size() : 0;
    }

    @Override
    public int getItemViewType(int position) {
        return mList.get(position).getType();
    }

    @Override
    public void onItemMoved(int from, int to) {
        notifyItemMoved(from, to);
    }
}

Я что-то пропустил? Или это просто возможно достичь?

Спасибо за все ваши ответы!

0 ответов

Другие вопросы по тегам