إنشاء قوائم ديناميكية باستخدام 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 customization.
تفعيل ميزة "العرض حتى حافة الشاشة"
اتّبِع الخطوات التالية لتفعيل ميزة "العرض حتى حافة الشاشة" لـ 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، يُرجى الاطّلاع على المراجع التالية.