Android 循环视图拖放功能

在本教程中,我们将讨论并在Android应用程序中实现拖放功能。我们已经在上一个教程中讨论了Swipe取消功能。

循环查看拖放

可以使用ItemTouchHelper实用程序类将拖放添加到RecillerView中。以下是ItemTouchHelper.Callback接口中需要实现的重要方法:

  • isLongPressDragEnabled-在此处返回TRUE,以启用在回收器视图行上长按拖放。
  • isItemViewSwipeEnabled-开启或关闭刷屏。在本教程中,我们将禁用此功能。
  • getMovementFlags-在这里我们传递拖动和滑动方向的标志。由于Swipe被禁用,因此我们为其传递0。
  • onMove-这里我们设置了拖放代码。Onwipe-在这里我们实现了用于滑动的代码。我们将在当前教程中将其保留为空。
  • onSelectedChanged--根据当前循环视图的状态,无论是按下还是滑动,都会触发该方法。在这里,我们可以定制RecclerView行。例如,更改背景颜色。
  • clearView--当用户停止与RecillerView行的交互时,触发该方法。

让我们开始构建我们的Android应用程序,并在RecclerView上使用拖放功能。

项目结构

安卓拖放recyclerview

代码

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来刷新适配器。上述应用程序的实际输出如下所示:Android Rececumerview Drag Drop output到目前为止,我们已经通过按下回收视图行中的任意位置进行了拖放。接下来,我们将看到如何通过仅按下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        });

您可以在本教程末尾的下载链接中找到更新后的代码。应用程序的输出和更新后的代码如下所示:Android Rececumerview拖放句柄output这将结束本教程。该项目的完整源代码如下:

AndroidRecyclerViewDragAndDrop

GitHub项目Link

Published At
Categories with 技术
Tagged with
comments powered by Disqus