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