在本教程中,我们将讨论并在Android应用程序中实现拖放功能。我们已经在上一个教程中讨论了Swipe取消功能。
循环查看拖放
可以使用ItemTouchHelper实用程序类将拖放添加到RecillerView中。以下是ItemTouchHelper.Callback
接口中需要实现的重要方法:
isLongPressDragEnabled
-在此处返回TRUE,以启用在回收器视图行上长按拖放。isItemViewSwipeEnabled
-开启或关闭刷屏。在本教程中,我们将禁用此功能。getMovementFlags
-在这里我们传递拖动和滑动方向的标志。由于Swipe被禁用,因此我们为其传递0。onMove
-这里我们设置了拖放代码。Onwipe-在这里我们实现了用于滑动的代码。我们将在当前教程中将其保留为空。onSelectedChanged
--根据当前循环视图的状态,无论是按下还是滑动,都会触发该方法。在这里,我们可以定制RecclerView行。例如,更改背景颜色。clearView
--当用户停止与RecillerView行的交互时,触发该方法。
让我们开始构建我们的Android应用程序,并在RecclerView上使用拖放功能。
项目结构
代码
Activity_main.xml布局的代码如下所示,该布局仅包含一个Recical View:
1<?xml version="1.0" encoding="utf-8"?>
2<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
3 xmlns:app="https://schemas.android.com/apk/res-auto"
4 xmlns:tools="https://schemas.android.com/tools"
5 android:layout_width="match_parent"
6 android:layout_height="match_parent"
7 tools:context=".MainActivity">
8
9 <android.support.v7.widget.RecyclerView
10 android:id="@+id/recyclerView"
11 android:layout_width="match_parent"
12 android:layout_height="wrap_content"
13 android:orientation="vertical"
14 app:layoutManager="android.support.v7.widget.LinearLayoutManager" />
15
16</LinearLayout>
MainActivity.java的代码如下所示:
1package com.journaldev.androidrecyclerviewdraganddrop;
2
3import android.support.v7.app.AppCompatActivity;
4import android.os.Bundle;
5import android.support.v7.widget.RecyclerView;
6import android.support.v7.widget.helper.ItemTouchHelper;
7
8import java.util.ArrayList;
9
10public class MainActivity extends AppCompatActivity {
11
12 RecyclerView recyclerView;
13 RecyclerViewAdapter mAdapter;
14 ArrayList<String> stringArrayList = new ArrayList<>();
15
16 @Override
17 protected void onCreate(Bundle savedInstanceState) {
18 super.onCreate(savedInstanceState);
19 setContentView(R.layout.activity_main);
20
21 recyclerView = findViewById(R.id.recyclerView);
22
23 populateRecyclerView();
24 }
25
26 private void populateRecyclerView() {
27 stringArrayList.add("Item 1");
28 stringArrayList.add("Item 2");
29 stringArrayList.add("Item 3");
30 stringArrayList.add("Item 4");
31 stringArrayList.add("Item 5");
32 stringArrayList.add("Item 6");
33 stringArrayList.add("Item 7");
34 stringArrayList.add("Item 8");
35 stringArrayList.add("Item 9");
36 stringArrayList.add("Item 10");
37
38 mAdapter = new RecyclerViewAdapter(stringArrayList);
39
40 ItemTouchHelper.Callback callback =
41 new ItemMoveCallback(mAdapter);
42 ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
43 touchHelper.attachToRecyclerView(recyclerView);
44
45 recyclerView.setAdapter(mAdapter);
46 }
47
48}
在这里,我们用一个字符串的ArrayList填充了一个Recical erViewAdapter.Java类。我们已经将ItemMoveCallback.Java类的一个实例附加到Recical erView上,以开始拖放。让我们看看这些文件中的每一个。ItemMoveCallback.Java类的代码如下所示:
1package com.journaldev.androidrecyclerviewdraganddrop;
2
3import android.support.annotation.NonNull;
4import android.support.v7.widget.RecyclerView;
5import android.support.v7.widget.helper.ItemTouchHelper;
6
7public class ItemMoveCallback extends ItemTouchHelper.Callback {
8
9 private final ItemTouchHelperContract mAdapter;
10
11 public ItemMoveCallback(ItemTouchHelperContract adapter) {
12 mAdapter = adapter;
13 }
14
15 @Override
16 public boolean isLongPressDragEnabled() {
17 return true;
18 }
19
20 @Override
21 public boolean isItemViewSwipeEnabled() {
22 return false;
23 }
24
25 @Override
26 public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
27
28 }
29
30 @Override
31 public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
32 int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
33 return makeMovementFlags(dragFlags, 0);
34 }
35
36 @Override
37 public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
38 RecyclerView.ViewHolder target) {
39 mAdapter.onRowMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
40 return true;
41 }
42
43 @Override
44 public void onSelectedChanged(RecyclerView.ViewHolder viewHolder,
45 int actionState) {
46
47 if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
48 if (viewHolder instanceof RecyclerViewAdapter.MyViewHolder) {
49 RecyclerViewAdapter.MyViewHolder myViewHolder=
50 (RecyclerViewAdapter.MyViewHolder) viewHolder;
51 mAdapter.onRowSelected(myViewHolder);
52 }
53
54 }
55
56 super.onSelectedChanged(viewHolder, actionState);
57 }
58 @Override
59 public void clearView(RecyclerView recyclerView,
60 RecyclerView.ViewHolder viewHolder) {
61 super.clearView(recyclerView, viewHolder);
62
63 if (viewHolder instanceof RecyclerViewAdapter.MyViewHolder) {
64 RecyclerViewAdapter.MyViewHolder myViewHolder=
65 (RecyclerViewAdapter.MyViewHolder) viewHolder;
66 mAdapter.onRowClear(myViewHolder);
67 }
68 }
69
70 public interface ItemTouchHelperContract {
71
72 void onRowMoved(int fromPosition, int toPosition);
73 void onRowSelected(RecyclerViewAdapter.MyViewHolder myViewHolder);
74 void onRowClear(RecyclerViewAdapter.MyViewHolder myViewHolder);
75
76 }
77
78}
这里我们定义了一个接口ItemTouchHelperContract
。它的每个方法都是从ItemTouchHelper.Callback
接口的实现方法中调用的。下面给出了RecillerViewAdapter.Java类的代码:
1package com.journaldev.androidrecyclerviewdraganddrop;
2
3import android.graphics.Color;
4import android.support.v7.widget.RecyclerView;
5import android.view.LayoutInflater;
6import android.view.View;
7import android.view.ViewGroup;
8import android.widget.TextView;
9
10import java.util.ArrayList;
11import java.util.Collections;
12
13public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> implements ItemMoveCallback.ItemTouchHelperContract {
14
15 private ArrayList<String> data;
16
17 public class MyViewHolder extends RecyclerView.ViewHolder {
18
19 private TextView mTitle;
20 View rowView;
21
22 public MyViewHolder(View itemView) {
23 super(itemView);
24
25 rowView = itemView;
26 mTitle = itemView.findViewById(R.id.txtTitle);
27 }
28 }
29
30 public RecyclerViewAdapter(ArrayList<String> data) {
31 this.data = data;
32 }
33
34 @Override
35 public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
36 View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.cardview_row, parent, false);
37 return new MyViewHolder(itemView);
38 }
39
40 @Override
41 public void onBindViewHolder(MyViewHolder holder, int position) {
42 holder.mTitle.setText(data.get(position));
43 }
44
45 @Override
46 public int getItemCount() {
47 return data.size();
48 }
49
50 @Override
51 public void onRowMoved(int fromPosition, int toPosition) {
52 if (fromPosition < toPosition) {
53 for (int i = fromPosition; i < toPosition; i++) {
54 Collections.swap(data, i, i + 1);
55 }
56 } else {
57 for (int i = fromPosition; i > toPosition; i--) {
58 Collections.swap(data, i, i - 1);
59 }
60 }
61 notifyItemMoved(fromPosition, toPosition);
62 }
63
64 @Override
65 public void onRowSelected(MyViewHolder myViewHolder) {
66 myViewHolder.rowView.setBackgroundColor(Color.GRAY);
67
68 }
69
70 @Override
71 public void onRowClear(MyViewHolder myViewHolder) {
72 myViewHolder.rowView.setBackgroundColor(Color.WHITE);
73
74 }
75}
拖放完成后,调用之前Contact接口中定义的onRowMoved
。在这里,我们交换了ArrayList中存在的两行的位置,并调用notfyItemMoved来刷新适配器。上述应用程序的实际输出如下所示:到目前为止,我们已经通过按下回收视图行中的任意位置进行了拖放。接下来,我们将看到如何通过仅按下RecclerView行中的特定视图来执行相同的操作。
使用手柄拖放
为了使用特定的句柄视图进行拖放,我们需要做以下事情:设置isLongPressDragEnabled
为False,关闭默认拖放。创建如下所示的界面:
1public interface StartDragListener {
2 void requestDrag(RecyclerView.ViewHolder viewHolder);
3}
在MainActivity上实现它,并将其传递给Adapter。
1@Override
2 public void requestDrag(RecyclerView.ViewHolder viewHolder) {
3 touchHelper.startDrag(viewHolder);
4 }
1mAdapter = new RecyclerViewAdapter(stringArrayList,this);
在RecEconerViewAdapter.java中执行以下操作:
1holder.imageView.setOnTouchListener(new View.OnTouchListener() {
2 @Override
3 public boolean onTouch(View v, MotionEvent event) {
4 if (event.getAction() ==
5 MotionEvent.ACTION_DOWN) {
6 mStartDragListener.requestDrag(holder);
7 }
8 return false;
9 }
10 });
您可以在本教程末尾的下载链接中找到更新后的代码。应用程序的输出和更新后的代码如下所示:这将结束本教程。该项目的完整源代码如下: