Перетаскивание Android RecyclerView
В этом руководстве мы обсудим и реализуем функцию перетаскивания через наш RecyclerView в приложении для Android. Мы уже обсуждали функцию Swipe to Dismiss в нашем предыдущем уроке.
Перетаскивание RecyclerView
Перетаскивание можно добавить в RecyclerView с помощью служебного класса ItemTouchHelper. Ниже перечислены важные методы интерфейса ItemTouchHelper.Callback
, которые необходимо реализовать:
isLongPressDragEnabled
— верните здесь значение true, чтобы включить длительное нажатие на строки RecyclerView для перетаскивания.isItemViewSwipeEnabled
— используется для включения или отключения свайпов. В этом уроке мы отключим это.getMovementFlags
— здесь мы передаем флаги для направлений перетаскивания и смахивания. Поскольку смахивание отключено, мы передаем для него 0.onMove
— здесь мы устанавливаем код для перетаскивания. onSwipe — Здесь мы реализуем код для свайпа. Мы оставим это поле пустым в текущем руководстве.onSelectedChanged
— этот метод срабатывает в зависимости от текущего состояния RecyclerView и от того, нажата она или пролистана. Здесь мы можем настроить строку RecyclerView. Например, изменение цвета фона.clearView
. Этот метод срабатывает, когда взаимодействие пользователя со строкой RecyclerView прекращается.
Давайте начнем создавать наше приложение для Android с функцией перетаскивания в RecyclerView.
Структура проекта
Код
Код макета activity_main.xml, который содержит только RecyclerView, приведен ниже:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layoutManager="android.support.v7.widget.LinearLayoutManager" />
</LinearLayout>
Код для MainActivity.java приведен ниже:
package com.journaldev.androidrecyclerviewdraganddrop;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
RecyclerViewAdapter mAdapter;
ArrayList<String> stringArrayList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recyclerView);
populateRecyclerView();
}
private void populateRecyclerView() {
stringArrayList.add("Item 1");
stringArrayList.add("Item 2");
stringArrayList.add("Item 3");
stringArrayList.add("Item 4");
stringArrayList.add("Item 5");
stringArrayList.add("Item 6");
stringArrayList.add("Item 7");
stringArrayList.add("Item 8");
stringArrayList.add("Item 9");
stringArrayList.add("Item 10");
mAdapter = new RecyclerViewAdapter(stringArrayList);
ItemTouchHelper.Callback callback =
new ItemMoveCallback(mAdapter);
ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
touchHelper.attachToRecyclerView(recyclerView);
recyclerView.setAdapter(mAdapter);
}
}
Здесь мы заполнили класс RecyclerViewAdapter.java списком строк ArrayList. Мы прикрепили экземпляр класса ItemMoveCallback.java к RecyclerView, чтобы начать перетаскивание. Давайте посмотрим на каждый из этих файлов. Код для класса ItemMoveCallback.java приведен ниже:
package com.journaldev.androidrecyclerviewdraganddrop;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
public class ItemMoveCallback extends ItemTouchHelper.Callback {
private final ItemTouchHelperContract mAdapter;
public ItemMoveCallback(ItemTouchHelperContract adapter) {
mAdapter = adapter;
}
@Override
public boolean isLongPressDragEnabled() {
return true;
}
@Override
public boolean isItemViewSwipeEnabled() {
return false;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
}
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
return makeMovementFlags(dragFlags, 0);
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
RecyclerView.ViewHolder target) {
mAdapter.onRowMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder,
int actionState) {
if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
if (viewHolder instanceof RecyclerViewAdapter.MyViewHolder) {
RecyclerViewAdapter.MyViewHolder myViewHolder=
(RecyclerViewAdapter.MyViewHolder) viewHolder;
mAdapter.onRowSelected(myViewHolder);
}
}
super.onSelectedChanged(viewHolder, actionState);
}
@Override
public void clearView(RecyclerView recyclerView,
RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
if (viewHolder instanceof RecyclerViewAdapter.MyViewHolder) {
RecyclerViewAdapter.MyViewHolder myViewHolder=
(RecyclerViewAdapter.MyViewHolder) viewHolder;
mAdapter.onRowClear(myViewHolder);
}
}
public interface ItemTouchHelperContract {
void onRowMoved(int fromPosition, int toPosition);
void onRowSelected(RecyclerViewAdapter.MyViewHolder myViewHolder);
void onRowClear(RecyclerViewAdapter.MyViewHolder myViewHolder);
}
}
Здесь мы определили интерфейс ItemTouchHelperContract
. Каждый из его методов вызывается из реализованных методов интерфейса ItemTouchHelper.Callback
. Код класса RecyclerViewAdapter.java приведен ниже:
package com.journaldev.androidrecyclerviewdraganddrop;
import android.graphics.Color;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Collections;
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> implements ItemMoveCallback.ItemTouchHelperContract {
private ArrayList<String> data;
public class MyViewHolder extends RecyclerView.ViewHolder {
private TextView mTitle;
View rowView;
public MyViewHolder(View itemView) {
super(itemView);
rowView = itemView;
mTitle = itemView.findViewById(R.id.txtTitle);
}
}
public RecyclerViewAdapter(ArrayList<String> data) {
this.data = data;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.cardview_row, parent, false);
return new MyViewHolder(itemView);
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.mTitle.setText(data.get(position));
}
@Override
public int getItemCount() {
return data.size();
}
@Override
public void onRowMoved(int fromPosition, int toPosition) {
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(data, i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(data, i, i - 1);
}
}
notifyItemMoved(fromPosition, toPosition);
}
@Override
public void onRowSelected(MyViewHolder myViewHolder) {
myViewHolder.rowView.setBackgroundColor(Color.GRAY);
}
@Override
public void onRowClear(MyViewHolder myViewHolder) {
myViewHolder.rowView.setBackgroundColor(Color.WHITE);
}
}
Перетаскивание с помощью манипуляторов
Чтобы использовать определенный вид дескриптора для перетаскивания, нам нужно сделать следующее: Установите для isLongPressDragEnabled
значение false, чтобы отключить перетаскивание по умолчанию. Создайте интерфейс, например:
public interface StartDragListener {
void requestDrag(RecyclerView.ViewHolder viewHolder);
}
Реализуйте его в MainActivity и передайте адаптеру.
@Override
public void requestDrag(RecyclerView.ViewHolder viewHolder) {
touchHelper.startDrag(viewHolder);
}
mAdapter = new RecyclerViewAdapter(stringArrayList,this);
Внутри RecyclerViewAdapter.java сделайте следующее:
holder.imageView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() ==
MotionEvent.ACTION_DOWN) {
mStartDragListener.requestDrag(holder);
}
return false;
}
});
AndroidRecyclerViewDragAndDrop
Ссылка на проект на гитхабе