สร้างรายการแบบไดนามิกด้วย RecyclerView เป็นส่วนหนึ่งของ Android Jetpack
RecyclerView ช่วยให้แสดงชุดข้อมูลขนาดใหญ่ได้อย่างมีประสิทธิภาพและง่ายดาย คุณเป็นผู้ระบุข้อมูลและกำหนดลักษณะของแต่ละรายการ และไลบรารี RecyclerView จะสร้างองค์ประกอบแบบไดนามิกเมื่อจำเป็น
RecyclerView จะรีไซเคิลองค์ประกอบแต่ละรายการตามชื่อของมัน เมื่อรายการเลื่อนออกจากหน้าจอ RecyclerView จะไม่ทำลายมุมมองของรายการนั้น แต่ RecyclerView จะนำมุมมองมาใช้ซ้ำสำหรับรายการใหม่ที่เลื่อนเข้ามาในหน้าจอ RecyclerView ช่วยปรับปรุงประสิทธิภาพและการตอบสนองของแอป รวมถึงลดการใช้พลังงาน
คลาสหลัก
คลาสหลายคลาสจะทำงานร่วมกันเพื่อสร้างรายการแบบไดนามิก
RecyclerViewคือViewGroupที่มีข้อมูลพร็อพเพอร์ตี้ที่สอดคล้องกับข้อมูลของคุณ เนื่องจากเป็นมุมมอง คุณจึงเพิ่มRecyclerViewลงในเลย์เอาต์ได้เช่นเดียวกับการเพิ่มองค์ประกอบ UI อื่นๆแต่ละองค์ประกอบในรายการจะกำหนดโดยออบเจ็กต์ view holder เมื่อสร้าง ViewHolder แล้ว จะไม่มีข้อมูลใดๆ ที่เชื่อมโยงกับ ViewHolder นั้น หลังจากสร้าง View Holder แล้ว
RecyclerViewจะเชื่อมโยง View Holder กับข้อมูลของตัวเอง คุณกำหนด ViewHolder โดยขยายRecyclerView.ViewHolderRecyclerViewจะขอข้อมูลพร็อพเพอร์ตี้และเชื่อมโยงข้อมูลพร็อพเพอร์ตี้กับข้อมูลของตนโดยเรียกใช้เมธอดใน adapter คุณกำหนดอะแดปเตอร์โดยขยายRecyclerView.Adapterเครื่องมือจัดการเลย์เอาต์จะจัดเรียงองค์ประกอบแต่ละรายการในรายการ คุณสามารถใช้เครื่องมือจัดการเลย์เอาต์ที่ไลบรารี RecyclerView มีให้ หรือจะกำหนดเองก็ได้ LayoutManager ทั้งหมดจะอิงตามคลาสแอบสแตรกต์
LayoutManagerของไลบรารี
คุณดูวิธีที่องค์ประกอบทั้งหมดทำงานร่วมกันได้ในแอปตัวอย่าง RecyclerView (Kotlin) หรือแอปตัวอย่าง RecyclerView (Java)
ขั้นตอนการติดตั้งใช้งาน RecyclerView
หากคุณจะใช้ RecyclerView คุณต้องทำสิ่งต่อไปนี้ ซึ่งจะอธิบายอย่างละเอียดในส่วนต่อไปนี้
เลือกรูปลักษณ์ของรายการหรือตารางกริด โดยปกติแล้ว คุณสามารถใช้เครื่องมือจัดการเลย์เอาต์มาตรฐานของไลบรารี RecyclerView ได้
ออกแบบลักษณะและลักษณะการทำงานของแต่ละองค์ประกอบในรายการ ขยายคลาส
ViewHolderโดยอิงตามการออกแบบนี้ViewHolderเวอร์ชันของคุณมีฟังก์ชันการทำงานทั้งหมดสำหรับรายการต่างๆ ตัวยึดมุมมองของคุณเป็น Wrapper รอบViewและมุมมองนั้นได้รับการจัดการโดยRecyclerViewกำหนด
Adapterที่เชื่อมโยงข้อมูลของคุณกับข้อมูลพร็อพเพอร์ตี้ViewHolder
นอกจากนี้ยังมีตัวเลือกการปรับแต่งขั้นสูงที่ช่วยให้คุณปรับแต่ง RecyclerView ให้ตรงกับความต้องการได้
วางแผนเลย์เอาต์
รายการใน RecyclerView จะจัดเรียงตามคลาส LayoutManager ไลบรารี RecyclerView มี LayoutManager 3 รายการ ซึ่งจัดการสถานการณ์เลย์เอาต์ที่พบบ่อยที่สุด ดังนี้
LinearLayoutManagerจัดเรียงรายการในลิสต์แบบมิติเดียวGridLayoutManagerจัดเรียงรายการในตารางกริด 2 มิติ- หากตารางกริดจัดเรียงในแนวตั้ง
GridLayoutManagerจะพยายามทำให้องค์ประกอบทั้งหมดในแต่ละแถวมีความกว้างและความสูงเท่ากัน แต่แถวที่ต่างกันอาจมีความสูงต่างกันได้ - หากตารางกริดจัดเรียงในแนวนอน
GridLayoutManagerจะพยายามทำให้องค์ประกอบทั้งหมดในแต่ละคอลัมน์มีความกว้างและความสูงเท่ากัน แต่คอลัมน์ต่างๆ อาจมีความกว้างต่างกันได้
- หากตารางกริดจัดเรียงในแนวตั้ง
StaggeredGridLayoutManagerคล้ายกับGridLayoutManagerแต่ไม่จำเป็นต้องให้รายการในแถวมีความสูงเท่ากัน (สำหรับตารางกริดแนวตั้ง) หรือรายการในคอลัมน์เดียวกันมีความกว้างเท่ากัน (สำหรับตารางกริดแนวนอน) ซึ่งส่งผลให้รายการในแถวหรือคอลัมน์อาจไม่ตรงกัน
นอกจากนี้ คุณยังต้องออกแบบเลย์เอาต์ของแต่ละรายการด้วย คุณต้องใช้เลย์เอาต์นี้เมื่อออกแบบตัวยึดมุมมองตามที่อธิบายไว้ในส่วนถัดไป
ติดตั้งใช้งานอะแดปเตอร์และ View Holder
เมื่อกำหนดเลย์เอาต์แล้ว คุณจะต้องใช้ Adapter และ ViewHolder คลาสทั้ง 2 คลาสนี้จะทำงานร่วมกันเพื่อกำหนดวิธีแสดงข้อมูล ViewHolder เป็น Wrapper รอบ View ที่มีเลย์เอาต์สำหรับแต่ละรายการในลิสต์ Adapter จะสร้างออบเจ็กต์ ViewHolder ตามความจำเป็น และตั้งค่าข้อมูลสำหรับมุมมองเหล่านั้นด้วย กระบวนการเชื่อมโยงมุมมองกับข้อมูลเรียกว่าการเชื่อมโยง
เมื่อกำหนดอะแดปเตอร์ คุณจะลบล้างเมธอดหลัก 3 เมธอดต่อไปนี้
onCreateViewHolder():RecyclerViewจะเรียกใช้เมธอดนี้เมื่อใดก็ตามที่ต้องการสร้างViewHolderใหม่ เมธอดนี้จะสร้างและเริ่มต้นViewHolderและViewที่เชื่อมโยง แต่จะไม่กรอกเนื้อหาของมุมมอง เนื่องจากViewHolderยังไม่ได้เชื่อมโยงกับข้อมูลที่เฉพาะเจาะจงonBindViewHolder():RecyclerViewเรียกใช้เมธอดนี้เพื่อเชื่อมโยงViewHolderกับข้อมูล เมธอดจะดึงข้อมูลที่เหมาะสมและใช้ข้อมูลเพื่อกรอกเลย์เอาต์ของ ViewHolder ตัวอย่างเช่น หากRecyclerViewแสดงรายการชื่อ เมธอดอาจค้นหาชื่อที่เหมาะสมในรายการและกรอกข้อมูลในวิดเจ็ตTextViewของ View HoldergetItemCount():RecyclerViewเรียกใช้เมธอดนี้เพื่อดูขนาดของชุดข้อมูล เช่น ในแอปสมุดที่อยู่ ข้อมูลนี้อาจเป็นจำนวนที่อยู่ทั้งหมด RecyclerView จะใช้ค่านี้เพื่อระบุว่าไม่มีรายการที่แสดงได้อีกต่อไป
ต่อไปนี้เป็นตัวอย่างทั่วไปของอะแดปเตอร์แบบง่ายที่มี ViewHolder ที่ฝังอยู่ซึ่งแสดงรายการข้อมูล ในกรณีนี้ RecyclerView จะแสดงรายการองค์ประกอบของข้อความแบบง่ายๆ ระบบจะส่งอาร์เรย์ของสตริงที่มีข้อความสำหรับองค์ประกอบ ViewHolder ไปยังอะแดปเตอร์
Kotlin
class CustomAdapter(private val dataSet: Array<String>) : RecyclerView.Adapter<CustomAdapter.ViewHolder>() { /** * Provide a reference to the type of views that you are using * (custom ViewHolder) */ class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { val textView: TextView init { // Define click listener for the ViewHolder's View textView = view.findViewById(R.id.textView) } } // Create new views (invoked by the layout manager) override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder { // Create a new view, which defines the UI of the list item val view = LayoutInflater.from(viewGroup.context) .inflate(R.layout.text_row_item, viewGroup, false) return ViewHolder(view) } // Replace the contents of a view (invoked by the layout manager) override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) { // Get element from your dataset at this position and replace the // contents of the view with that element viewHolder.textView.text = dataSet[position] } // Return the size of your dataset (invoked by the layout manager) override fun getItemCount() = dataSet.size }
Java
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> { private String[] localDataSet; /** * Provide a reference to the type of views that you are using * (custom ViewHolder) */ public static class ViewHolder extends RecyclerView.ViewHolder { private final TextView textView; public ViewHolder(View view) { super(view); // Define click listener for the ViewHolder's View textView = (TextView) view.findViewById(R.id.textView); } public TextView getTextView() { return textView; } } /** * Initialize the dataset of the Adapter * * @param dataSet String[] containing the data to populate views to be used * by RecyclerView */ public CustomAdapter(String[] dataSet) { localDataSet = dataSet; } // Create new views (invoked by the layout manager) @Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { // Create a new view, which defines the UI of the list item View view = LayoutInflater.from(viewGroup.getContext()) .inflate(R.layout.text_row_item, viewGroup, false); return new ViewHolder(view); } // Replace the contents of a view (invoked by the layout manager) @Override public void onBindViewHolder(ViewHolder viewHolder, final int position) { // Get element from your dataset at this position and replace the // contents of the view with that element viewHolder.getTextView().setText(localDataSet[position]); } // Return the size of your dataset (invoked by the layout manager) @Override public int getItemCount() { return localDataSet.length; } }
เลย์เอาต์สำหรับรายการมุมมองแต่ละรายการจะกำหนดไว้ในไฟล์เลย์เอาต์ XML ตามปกติ
ในกรณีนี้ แอปจะมีไฟล์ text_row_item.xml ดังนี้
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/list_item_height"
android:layout_marginLeft="@dimen/margin_medium"
android:layout_marginRight="@dimen/margin_medium"
android:gravity="center_vertical">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/element_text"/>
</FrameLayout>
ขั้นตอนถัดไป
ข้อมูลโค้ดต่อไปนี้แสดงวิธีใช้ RecyclerView
Kotlin
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val dataset = arrayOf("January", "February", "March") val customAdapter = CustomAdapter(dataset) val recyclerView: RecyclerView = findViewById(R.id.recycler_view) recyclerView.layoutManager = LinearLayoutManager(this) recyclerView.adapter = customAdapter } }
Java
RecyclerView recyclerView = findViewById(R.id.recycler_view); recyclerView.layoutManager = new LinearLayoutManager(this) recyclerView.setAdapter(customAdapter);
นอกจากนี้ ไลบรารียังมีวิธีมากมายในการปรับแต่งการติดตั้งใช้งาน ดูข้อมูลเพิ่มเติมได้ที่การปรับแต่ง RecyclerView ขั้นสูง
เปิดใช้การแสดงผลแบบไร้ขอบ
ทำตามขั้นตอนต่อไปนี้เพื่อเปิดใช้การแสดงผลแบบไร้ขอบสำหรับ RecyclerView
- ตั้งค่าการแสดงผลแบบไร้ขอบที่เข้ากันได้แบบย้อนหลังโดยเรียกใช้
enableEdgeToEdge() - หากรายการในลิสต์ซ้อนทับกับแถบระบบในตอนแรก ให้ใช้ส่วนแทรกกับ
RecyclerViewซึ่งทำได้โดยตั้งค่าandroid:fitsSystemWindowsเป็นtrueหรือใช้ViewCompat.setOnApplyWindowInsetsListener - อนุญาตให้รายการแสดงใต้แถบระบบขณะเลื่อนโดยตั้งค่า
android:clipToPaddingเป็นfalseในRecyclerView
วิดีโอต่อไปนี้แสดง RecyclerView ที่ปิดใช้การแสดงผลแบบไร้ขอบ (ซ้าย) และเปิดใช้ (ขวา)
ตัวอย่างโค้ดแทรก
Kotlin
ViewCompat.setOnApplyWindowInsetsListener( findViewById(R.id.my_recycler_view) ) { v, insets -> val innerPadding = insets.getInsets( WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout() // If using EditText, also add // "or WindowInsetsCompat.Type.ime()" to // maintain focus when opening the IME ) v.setPadding( innerPadding.left, innerPadding.top, innerPadding.right, innerPadding.bottom) insets }
Java
ViewCompat.setOnApplyWindowInsetsListener( activity.findViewById(R.id.my_recycler_view), (v, insets) -> { Insets innerPadding = insets.getInsets( WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout() // If using EditText, also add // "| WindowInsetsCompat.Type.ime()" to // maintain focus when opening the IME ); v.setPadding( innerPadding.left, innerPadding.top, innerPadding.right, innerPadding.bottom ); return insets; } );
XML ของ RecyclerView:
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/my_recycler_view"
android:clipToPadding="false"
android:layout_width="match_parent"
android:layout_height="match_parent" />
แหล่งข้อมูลเพิ่มเติม
ดูข้อมูลเพิ่มเติมเกี่ยวกับการทดสอบใน Android ได้ที่แหล่งข้อมูลต่อไปนี้