إنشاء قوائم ديناميكية باستخدام RecyclerView أحد مكونات Android Jetpack.
تسهّل أداة RecyclerView عرض مجموعات كبيرة من البيانات بكفاءة. يمكنك توفير البيانات وتحديد شكل كل عنصر، وستنشئ مكتبة RecyclerView العناصر ديناميكيًا عند الحاجة إليها.
وكما يوحي الاسم، فإنّ RecyclerView يعيد استخدام هذه العناصر الفردية. عندما يتم تمرير عنصر خارج الشاشة، لا يزيل RecyclerView طريقة العرض الخاصة به. بدلاً من ذلك، يعيد RecyclerView استخدام طريقة العرض للعناصر الجديدة التي تم الانتقال إليها على الشاشة. تعمل أداة RecyclerView على تحسين الأداء وسرعة استجابة تطبيقك، كما أنّها تقلّل من استهلاك الطاقة.
الفئات الرئيسية
تعمل عدة فئات معًا لإنشاء قائمتك الديناميكية.
RecyclerView
هوViewGroup
الذي يحتوي على المشاهدات المطابقة لبياناتك. وهي طريقة عرض بحد ذاتها، لذا يمكنك إضافةRecyclerView
إلى التصميم بالطريقة نفسها التي تضيف بها أي عنصر آخر من عناصر واجهة المستخدم.يتم تحديد كل عنصر فردي في القائمة من خلال عنصر حاوية العرض. عند إنشاء عنصر نائب للعرض، لا تكون هناك أي بيانات مرتبطة به. بعد إنشاء عنصر نائب للعرض،
RecyclerView
يربطه ببياناته. يمكنك تحديد عنصر نائب العرض من خلال توسيعRecyclerView.ViewHolder
.يرسل
RecyclerView
طلبات للحصول على طرق العرض، ويربط طرق العرض بالبيانات من خلال استدعاء طرق في المحوّل. يمكنك تحديد المحوّل من خلال توسيعRecyclerView.Adapter
.يعمل مدير التنسيق على ترتيب العناصر الفردية في قائمتك. يمكنك استخدام أحد أدوات إدارة التنسيق التي توفّرها مكتبة RecyclerView، أو يمكنك تحديد أداة خاصة بك. تستند جميع أدوات إدارة التنسيق إلى فئة
LayoutManager
المجردة في المكتبة.
يمكنك الاطّلاع على كيفية عمل كل الأجزاء معًا في تطبيق RecyclerView النموذجي (Kotlin) أو تطبيق RecyclerView النموذجي (Java).
خطوات تنفيذ RecyclerView
إذا كنت ستستخدم RecyclerView، هناك بعض الإجراءات التي عليك اتّخاذها، وسيتم شرحها بالتفصيل في الأقسام التالية.
حدِّد شكل القائمة أو الشبكة. في العادة، يمكنك استخدام أحد أدوات إدارة التنسيق العادية في مكتبة RecyclerView.
صمِّم شكل كل عنصر في القائمة وطريقة عمله. استنادًا إلى هذا التصميم، وسِّع نطاق الفئة
ViewHolder
. يوفّر إصدارViewHolder
جميع الوظائف لعناصر القائمة. حاوية العرض هي غلاف حولView
، وتتم إدارة هذا العرض من خلالRecyclerView
.حدِّد
Adapter
الذي يربط بياناتك بطرق العرضViewHolder
.
تتوفّر أيضًا خيارات تخصيص متقدّمة تتيح لك تخصيص RecyclerView حسب احتياجاتك بالضبط.
التخطيط للتصميم
يتم ترتيب العناصر في RecyclerView حسب فئة
LayoutManager
. توفّر مكتبة RecyclerView ثلاثة أدوات لتنظيم التصميم، وتتعامل هذه الأدوات مع حالات التصميم الأكثر شيوعًا:
LinearLayoutManager
ترتّب العناصر في قائمة أحادية البُعد.GridLayoutManager
ترتّب العناصر في شبكة ثنائية الأبعاد:- إذا تم ترتيب الشبكة عموديًا، تحاول
GridLayoutManager
أن يكون لجميع العناصر في كل صف العرض والارتفاع نفسهما، ولكن يمكن أن يكون للصفوف المختلفة ارتفاعات مختلفة. - إذا تم ترتيب الشبكة أفقيًا، تحاول
GridLayoutManager
أن يكون لجميع العناصر في كل عمود العرض والارتفاع نفسهما، ولكن يمكن أن يكون للأعمدة المختلفة عروض مختلفة.
- إذا تم ترتيب الشبكة عموديًا، تحاول
StaggeredGridLayoutManager
يشبهGridLayoutManager
، ولكنّه لا يشترط أن تتساوى ارتفاعات العناصر في الصف الواحد (بالنسبة إلى الشبكات العمودية) أو أن تتساوى عروض العناصر في العمود الواحد (بالنسبة إلى الشبكات الأفقية). ونتيجةً لذلك، قد يتم إزاحة العناصر في صف أو عمود عن بعضها البعض.
عليك أيضًا تصميم تخطيط العناصر الفردية. تحتاج إلى هذا التصميم عند تصميم حاوية العرض، كما هو موضّح في القسم التالي.
تنفيذ المحوّل وعنصر العرض
بعد تحديد التنسيق، عليك تنفيذ Adapter
وViewHolder
. تعمل هاتان الفئتان معًا لتحديد طريقة عرض بياناتك. ViewHolder
هو برنامج تضمين حول View
يحتوي على
تنسيق عنصر فردي في القائمة. ينشئ Adapter
عناصر ViewHolder
حسب الحاجة، ويضبط أيضًا البيانات الخاصة بطرق العرض هذه. تُعرف عملية ربط طرق العرض ببياناتها باسم الربط.
عند تحديد المحوّل، يمكنك إلغاء ثلاث طرق رئيسية:
onCreateViewHolder()
: يستدعيRecyclerView
هذه الطريقة عندما يحتاج إلى إنشاءViewHolder
جديد. تنشئ الطريقةViewHolder
وView
المرتبط بها وتهيّئهما، ولكنها لا تملأ محتويات العرض، لأنّViewHolder
لم يتم ربطه بعد ببيانات معيّنة.
onBindViewHolder()
: تستدعيRecyclerView
هذه الطريقة لربطViewHolder
بالبيانات. يجلب هذا الإجراء البيانات المناسبة ويستخدمها لملء تصميم حاوية العرض. على سبيل المثال، إذا كانRecyclerView
يعرض قائمة بأسماء، قد تعثر الطريقة على الاسم المناسب في القائمة وتملأ أداةTextView
في حاوية العرض.
getItemCount()
: تستدعي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; } );
RecyclerView
XML:
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/my_recycler_view"
android:clipToPadding="false"
android:layout_width="match_parent"
android:layout_height="match_parent" />
مراجع إضافية
لمزيد من المعلومات حول الاختبار على Android، يُرجى الرجوع إلى المراجع التالية.