Android RecyclerView拖放
在本教程中,我们将在Android应用程序中通过RecyclerView讨论和实现拖放功能。
我们已经在上一教程中讨论了"滑动以关闭"功能。
RecyclerView拖放
可以使用ItemTouchHelper实用工具类在RecyclerView中添加拖放。
以下是ItemTouchHelper.Callback接口中需要实现的重要方法:
isLongPressDragEnabled-在此处返回true,以使长按RecyclerView行以进行拖放。
isItemViewSwipeEnabled-用于启用或者禁用滑动。
在本教程中,我们将禁用它。getMovementFlags–其中我们传递用于拖动和滑动方向的标志。
由于禁用了滑动,因此我们将其传递为0。onMove –其中我们为拖放设置代码。
onSwipe –其中我们实现了刷卡代码。
在本教程中,我们将其保留为空。
" onSelectedChanged" –根据RecyclerView的当前状态以及是否按下或者滑动,都会触发此方法。
其中我们可以自定义RecyclerView行。
例如,更改背景颜色。clearView-当用户与RecyclerView行停止交互时,将触发此方法。
让我们开始使用RecyclerView上的拖放功能来构建我们的android应用程序。
代码
下面给出了仅包含RecyclerView的activity_main.xml布局的代码:
<?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.theitroad.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);
}
}
在此,我们用字符串的ArrayList填充了RecyclerViewAdapter.java类。
我们已经在RecyclerView上附加了ItemMoveCallback.java类的实例,以开始拖放操作。
让我们看一下每个文件。
下面给出了ItemMoveCallback.java类的代码:
package com.theitroad.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.theitroad.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);
}
}
完成拖放操作后,将调用先前在Contract接口中定义的onRowMoved。
其中我们交换ArrayList中存在的两行的位置,并调用notifyItemMoved刷新适配器。
上面应用程序的输出如下:
到目前为止,我们已经通过在RecyclerView行中按任意位置来完成拖放操作。
接下来,我们将看到如何通过仅按RecyclerView行内的特定视图来执行相同的操作。
使用手柄拖放
为了使用特定的手柄视图进行拖放,我们需要做以下事情:
将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;
}
});
您可以在本教程末尾的下载链接中找到更新的代码。

