如何在Android应用中实现RecyclerView的拖放功能?
在Android应用中,我们经常看到数据以列表形式显示,例如在任务追踪器应用中,不同类型的任务以特定顺序排列成列表。在这些应用中,我们可以通过简单地更改任务优先级来更改任务的优先级。我们将把优先级最高的任务放在顶部。因此,我们可以简单地将该任务拖放到最顶端的位置。这样,拖放功能就用于排列RecyclerView的这些项目。
实现
我们将创建一个简单的应用程序,其中我们将以RecyclerView的形式显示编程语言列表。我们将向该RecyclerView添加功能,以便用户可以根据自己的喜好拖放RecyclerView中的项目。
步骤1:在Android Studio中创建一个新项目
导航到Android Studio,如下图所示。在下图中,单击“新建项目”以创建一个新的Android Studio项目。
单击“新建项目”后,您将看到如下屏幕。
在这个屏幕中,我们只需选择“空活动”,然后单击“下一步”。单击“下一步”后,您将看到如下屏幕。
在这个屏幕中,我们只需指定项目名称。然后包名将自动生成。
注意 - 请确保选择Java作为语言。
指定所有详细信息后,单击“完成”以创建一个新的Android Studio项目。
项目创建完成后,我们将看到打开的两个文件,即activity_main.xml和MainActivity.java文件。
步骤2:使用activity_main.xml
导航到activity_main.xml。如果此文件不可见,则要打开此文件,请在左侧窗格中导航到app>res>layout>activity_main.xml以打开此文件。打开此文件后,向其中添加以下代码。代码中添加了注释以详细了解。
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <!-- creating a recycler view on below line --> <androidx.recyclerview.widget.RecyclerView android:id="@+id/idRVLanguages" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout>
说明:在上面的代码中,我们创建一个根布局作为相对布局。在这个布局中,我们创建一个RecyclerView,我们将在其中显示编程语言列表。
步骤3:为RecyclerView的数据创建一个模型类
导航到app>java>你的应用包名>右键单击它>新建>Java类,并将其命名为LanguageRVModal,然后向其中添加以下代码。代码中添加了注释以详细了解。
package com.example.java_test_application; public class LanguageRVModal { // on below line creating a variable for language name. private String languageName; // on below line creating constructor, getter and setters for it. public LanguageRVModal(String languageName) { this.languageName = languageName; } public String getLanguageName() { return languageName; } public void setLanguageName(String languageName) { this.languageName = languageName; } }
说明:在上面的代码中,我们为语言名称创建一个变量,并为该特定变量创建构造函数、getter和setter方法。
步骤4:为RecyclerView的每个项目创建一个布局文件
导航到app>res>layout>右键单击它>新建布局资源文件,并将其命名为language_rv_item,然后向其中添加以下代码。代码中添加了注释以详细了解。
<?xml version="1.0" encoding="utf-8"?> <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/idCVCard" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="5dp" app:cardCornerRadius="5dp"> <!-- creating a relative layout on below line--> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="4dp"> <!-- creating a text view on below line --> <TextView android:id="@+id/idTVLanguage" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="10dp" android:text="Language Name" android:textColor="@color/black" android:textSize="16sp" android:textStyle="bold" /> </RelativeLayout> </androidx.cardview.widget.CardView>
说明:在上面的代码中,我们创建一个CardView作为根布局。在这个CardView中,我们创建一个相对布局,在这个相对布局中,我们创建一个TextView,我们将使用它在RecyclerView中显示编程语言。
步骤5:创建一个适配器类,用于将数据设置为RecyclerView的每个项目
导航到app>java>你的应用包名>右键单击它>新建Java类,并将其命名为LanguageRVAdapter,然后向其中添加以下代码。代码中添加了注释以详细了解。
package com.example.java_test_application; import android.content.Context; import android.graphics.Color; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.cardview.widget.CardView; import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList; import java.util.Collections; public class LanguageRVAdapter extends RecyclerView.Adapter<LanguageRVAdapter.ViewHolder> implements RecyclerRowMoveCallback.ItemTouchHelperContract { // creating variables for array list and context on below line. private Context context; private ArrayList<LanguageRVModal> languageRVModals; // creating a constructore for recycler view on below line. public LanguageRVAdapter(Context context, ArrayList<LanguageRVModal> languageRVModals) { this.context = context; this.languageRVModals = languageRVModals; } @NonNull @Override public LanguageRVAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { // creating and initializing view for inflating layout. View view = LayoutInflater.from(context).inflate(R.layout.language_rv_item, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(@NonNull LanguageRVAdapter.ViewHolder holder, int position) { // setting data to our recycler view item. holder.languageTV.setText(languageRVModals.get(position).getLanguageName()); } @Override public int getItemCount() { // returning the size of array list. return languageRVModals.size(); } @Override public void onRowMoved(int fromPosition, int toPosition) { // on below line setting on row moved and swaping the items of recycler view. if (fromPosition < toPosition) { for (int i = fromPosition; i < toPosition; i++) { Collections.swap(languageRVModals, i, i + 1); } } else { for (int i = fromPosition; i > toPosition; i--) { Collections.swap(languageRVModals, i, i - 1); } } // on below line notifying item has been moved. notifyItemMoved(fromPosition, toPosition); } @Override public void onRowSelected(ViewHolder viewHolder) { // on below line setting selected item back color viewHolder.cardView.setBackgroundColor(Color.GRAY); } @Override public void onRowClear(ViewHolder viewHolder) { // on below line setting color for cleared row. viewHolder.cardView.setBackgroundColor(Color.WHITE); } public class ViewHolder extends RecyclerView.ViewHolder { // on below line creating variable for text view and card view. private TextView languageTV; private CardView cardView; public ViewHolder(@NonNull View itemView) { super(itemView); // on below line initializing this variables. languageTV = itemView.findViewById(R.id.idTVLanguage); cardView = itemView.findViewById(R.id.idCVCard); } } }
说明 - 在上面的代码中,我们正在膨胀我们创建的布局文件,该文件将为RecyclerView的每个项目显示。此外,它还用于将数据设置为RecyclerView的每个项目。
步骤6:创建一个新的Java类,用于移动RecyclerView中的项目
导航到app>java>你的应用包名>右键单击它>新建Java类,并将其命名为RecyclerRowMoveCallback,然后向其中添加以下代码。代码中添加了注释以详细了解。
package com.example.java_test_application; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.RecyclerView; public class RecyclerRowMoveCallback extends ItemTouchHelper.Callback { // on below line creating variable for item touch helper contract. private final ItemTouchHelperContract itemTouchHelperContract; // on below line creating a constructor for it. public RecyclerRowMoveCallback(ItemTouchHelperContract adapter) { itemTouchHelperContract = adapter; } @Override public boolean isItemViewSwipeEnabled() { return false; } @Override public boolean isLongPressDragEnabled() { return true; } @Override public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { // on below line setting drag flags to move up and down. int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; return makeMovementFlags(dragFlags, 0); } @Override public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) { // on below line setting on row moved. this.itemTouchHelperContract.onRowMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition()); return true; } @Override public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { } @Override public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) { // on below line changing the selected item. if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) { if (viewHolder instanceof LanguageRVAdapter.ViewHolder) { LanguageRVAdapter.ViewHolder myViewHolder = (LanguageRVAdapter.ViewHolder) viewHolder; this.itemTouchHelperContract.onRowSelected(myViewHolder); } } super.onSelectedChanged(viewHolder, actionState); } @Override public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { super.clearView(recyclerView, viewHolder); // on below line clearing the view. if (viewHolder instanceof LanguageRVAdapter.ViewHolder) { LanguageRVAdapter.ViewHolder myViewHolder = (LanguageRVAdapter.ViewHolder) viewHolder; this.itemTouchHelperContract.onRowClear(myViewHolder); } } // on below line creating an interface and creating methods in it. public interface ItemTouchHelperContract { void onRowMoved(int fromPosition, int toPosition); void onRowSelected(LanguageRVAdapter.ViewHolder myViewHolder); void onRowClear(LanguageRVAdapter.ViewHolder myViewHolder); } }
说明:在上面的代码中,我们创建了不同的方法,我们将使用这些方法来拖放RecyclerView的项目。
步骤7:使用MainActivity.java文件
导航到MainActivity.java。如果此文件不可见,则要打开此文件,请在左侧窗格中导航到app>res>layout>MainActivity.java以打开此文件。打开此文件后,向其中添加以下代码。代码中添加了注释以详细了解。
package com.example.java_test_application; import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList; public class MainActivity extends AppCompatActivity { // creating variables on below line for recycler view and adapter. private RecyclerView recyclerView; private LanguageRVAdapter languageRVAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // initializing variables on below line. recyclerView = findViewById(R.id.idRVLanguages); // creating an array list and initializing it ArrayListlanguageRVModals = new ArrayList<>(); // adding data to array list on below line. languageRVModals.add(new LanguageRVModal("Java")); languageRVModals.add(new LanguageRVModal("C")); languageRVModals.add(new LanguageRVModal("C++")); languageRVModals.add(new LanguageRVModal("Python")); languageRVModals.add(new LanguageRVModal("Kotlin")); languageRVModals.add(new LanguageRVModal("Dart")); // initializing adapter for recycler view. languageRVAdapter = new LanguageRVAdapter(this, languageRVModals); // setting layout manager for recycler view. recyclerView.setLayoutManager(new LinearLayoutManager(this)); // setting item touch helper for recycler view ItemTouchHelper.Callback callback = new RecyclerRowMoveCallback(languageRVAdapter); // initializing item touch helper on below line. ItemTouchHelper touchHelper = new ItemTouchHelper(callback); // attaching the touch helper to recycler view. touchHelper.attachToRecyclerView(recyclerView); // setting adapter for recycler view on below line. recyclerView.setAdapter(languageRVAdapter); } }
说明:在上面的代码中,我们首先为我们的RecyclerView和适配器创建变量。现在我们将看到onCreate方法。这是每个Android应用程序的默认方法。创建应用程序视图时会调用此方法。在此方法中,我们设置内容视图,即名为activity_main.xml的布局文件,以设置该文件中的UI。在onCreate方法中,我们初始化RecyclerView和适配器的变量。我们正在创建一个ArrayList并向其中添加数据。同时,我们将此适配器设置为我们的RecyclerView。我们还向其中添加了一个ItemTouchHelper,以便我们可以拖放RecyclerView中的项目。
添加上述代码后,我们只需单击顶部栏中的绿色图标即可在移动设备上运行我们的应用程序。
注意 - 请确保已连接到您的真实设备或模拟器。
输出
结论
在本文中,我们了解了如何在Android应用程序中为RecyclerView实现拖放功能。