如何在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
       ArrayList languageRVModals = 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實現拖放功能。

更新於:2023年5月8日

726 次瀏覽

啟動你的職業生涯

完成課程後獲得認證

開始學習
廣告