Android RecyclerView拖放

本文介绍了如何在Android应用中为RecyclerView实现拖放功能。通过使用ItemTouchHelper类,详细讲解了如何启用拖放,禁用滑动,以及自定义拖放操作时RecyclerView行的样式。此外,还展示了如何通过特定手柄视图进行拖放操作。
摘要由CSDN通过智能技术生成

In this tutorial, we’ll be discussing and implementing the Drag and Drop functionality over our RecyclerView in an Android Application. We’ve already discussed Swipe to Dismiss feature in our previous tutorial.

在本教程中,我们将在Android应用程序中的RecyclerView上讨论和实现拖放功能。 在上一教程中,我们已经讨论了“滑动以关闭”功能。

RecyclerView拖放 (RecyclerView Drag and Drop)

Drag and Drop can be added in a RecyclerView using the ItemTouchHelper utility class.

可以使用ItemTouchHelper实用程序类在RecyclerView中添加拖放。

Following are the important methods in the ItemTouchHelper.Callback interface which needs to be implemented:

以下是ItemTouchHelper.Callback接口中需要实现的重要方法:

  • isLongPressDragEnabled – return true here to enable long press on the RecyclerView rows for drag and drop.

    isLongPressDragEnabled –在此处返回true,以使长按RecyclerView行以进行拖放。
  • isItemViewSwipeEnabled – This is used to enable or disable swipes. In this tutorial, we’ll disable this.

    isItemViewSwipeEnabled –用于启用或禁用滑动。 在本教程中,我们将禁用它。
  • getMovementFlags – Here we pass the flags for the directions of drag and swipe. Since swipe is disable we pass 0 for it.

    getMovementFlags –在这里,我们传递用于拖动和滑动方向的标志。 由于禁用了滑动,因此我们将其传递为0。
  • onMove – Here we set the code for the drag and drop.
    onSwipe – Here we implement the code for swiping. We’ll keep this empty in the current tutorial.

    onMove –在这里,我们为拖放设置代码。
    onSwipe –在这里,我们实现了刷卡代码。 在本教程中,我们将其保留为空。
  • onSelectedChanged – Based on the current state of the RecyclerView and whether it’s pressed or swiped, this method gets triggered. Here we can customize the RecyclerView row. For example, changing the background color.

    onSelectedChanged –根据RecyclerView的当前状态以及是否按下或滑动,将触发此方法。 在这里,我们可以自定义RecyclerView行。 例如,更改背景颜色。
  • clearView – This method gets triggered when the user interaction stops with the RecyclerView row.

    clearView –当用户与RecyclerView行停止交互时,将触发此方法。

Let’s start building our android application with the drag and drop feature on the RecyclerView.

让我们开始使用RecyclerView上的拖放功能来构建我们的android应用程序。

项目结构 (Project Structure)

(Code)

The code for the activity_main.xml layout which contains a RecyclerView only is given below:

下面给出了仅包含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>

The code for the MainActivity.java is given below:

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);
    }

}

In this, we’ve populated a RecyclerViewAdapter.java class with an ArrayList of Strings.

在此,我们用字符串的ArrayList填充了RecyclerViewAdapter.java类。

We’ve attached an instance of the ItemMoveCallback.java class on the RecyclerView to start drag and drop.

我们已经在RecyclerView上附加了ItemMoveCallback.java类的实例,以开始拖放操作。

Let’s look at each of these files.

让我们看一下每个文件。

The code for the ItemMoveCallback.java class is given below:

下面给出了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);

    }

}

Here, we’ve defined an interface ItemTouchHelperContract. Each of its methods get called from the implemented methods of the ItemTouchHelper.Callback interface.

在这里,我们定义了一个接口ItemTouchHelperContract 。 它的每个方法都可以从ItemTouchHelper.Callback接口的已实现方法中ItemTouchHelper.Callback

The code for the RecyclerViewAdapter.java class is given below:

下面给出了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);

    }
}

onRowMoved defined in the Contract interface earlier gets called when the drag and drop is done.
Here we swap the positions of the two rows present in the ArrayList and call notifyItemMoved to refresh the adapter.

完成拖放操作后,将更早调用Contract接口中定义的onRowMoved
在这里,我们交换ArrayList中存在的两行的位置,并调用notifyItemMoved刷新适配器。

The output of the above application in action is given below:

上面应用程序的输出如下:

Up until now, we’ve done the drag and drop by pressing anywhere in the RecyclerView rows.
Next, we’ll see how to do the same by pressing only a particular view inside the RecyclerView row.

到目前为止,我们已经通过在RecyclerView行中的任意位置进行了拖放。
接下来,我们将看到如何通过仅按RecyclerView行内的特定视图来执行相同的操作。

使用手柄拖放 (Drag And Drop using Handles)

In order to use a specific handle view to drag and drop we need to do the following things:

为了使用特定的手柄视图进行拖放,我们需要执行以下操作:

Set isLongPressDragEnabled to false to disable the default drag and drop.

isLongPressDragEnabled设置为false可禁用默认的拖放。

Create an interface like:

创建一个界面,如:

public interface StartDragListener {
    void requestDrag(RecyclerView.ViewHolder viewHolder);
}

Implement it on the MainActivity and pass it to the Adapter.

在MainActivity上实现它,并将其传递给适配器。

@Override
    public void requestDrag(RecyclerView.ViewHolder viewHolder) {
        touchHelper.startDrag(viewHolder);
    }
mAdapter = new RecyclerViewAdapter(stringArrayList,this);

Inside the RecyclerViewAdapter.java do the following:

在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;
            }
        });

You can find the updated code in the download link at the end of this tutorial.

您可以在本教程末尾的下载链接中找到更新的代码。

The output of the application with the updated code is given below:

带有更新代码的应用程序输出如下:

This brings an end to this tutorial. The complete source code of the project is given below:

本教程到此结束。 该项目的完整源代码如下:

翻译自: https://www.journaldev.com/23208/android-recyclerview-drag-and-drop

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值