طريقه إنشاء custom adapter مع listview
السلام عليكم ورحمه الله وبركاته
في هذه المقاله شرح بسيط عن كيفيه إنشاء custom adapter مع listview.
الخطوات:
1- كلاس لتهيئة المتغيرات.
2- نضع ListView في ملف xml
3- ملف xml لتصميم الصف في ListView
4- كلاس myAdapter و ViewHolder pattern
5- في كلاس MainActivity نضيف القيم إلى ArrayList و نعرض البيانات في ListView
بالبداية نقوم بإنشاء كلاس Model لتهيئه المتغيرات مثل الأسم و صوره و دوال getter للوصول للمتغيرات لاحقا
Model.java public class Model { private String name; private int image; public Model(String name, int image) { this.name = name; this.image = image; } public String getName() { return name; } public int getImage() { return image; } }
في ملف activity_main.xml نضع ListView
activity_main.xml <ListView 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" android:id="@+id/listView" tools:context="com.example.thekra.customadapter.MainActivity"> </ListView>
ثم نقوم بإنشاء item.xml جديد وهو التنسيق للصف الواحد الذي سيظهر في ListView
item.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" xmlns:tools="http://schemas.android.com/tools"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="50dp" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_alignParentTop="true" tools:text="Testing" /> <ImageView android:id="@+id/image" android:layout_width="50dp" android:layout_height="50dp" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:src="@drawable/ic_launcher_background" /> </RelativeLayout>
ثم نقوم بإنشاء كلاس الادابتر الخاص بنا ونسميه myAdapter ونجعله يرث من كلاس الأب ArrayAdapter
بسبب ان ArrayAdapter لا يحتوي على constructor افتراضي سوف نحدد argument في constructor وهي context, layout, list
ملاحظه: ArrayAdapter سوف يضع TextView فقط في خانة layout لذلك نضع 0 لأننا لا نريد فقط TextView إنما تصميم معين خاص بنا على سبيل المثال TextView و ImageView
myAdapter.java public class myAdapter extends ArrayAdapter<Model> { private Context context; private List<Model> list; public myAdapter(Context context, List<Model> list) { super(context, 0, list); } }
في نفس الكلاس نعمل Override لميثود getView التي ترجع لنا View
نقوم بإنشاء متغير لمعرفة مكان عنصر محدد في ArrayList بإستخدام ميثود getItem()
ثم سوف نأخذ أوبجكت من كلاس LayoutInflater و وظيفته إنشاء Views من ملف item.xml
ثم نربط الViews في ملف item.xml مع ملف الجافا بواسطه findViewById()
و نرفق القيم الى views بواسطة setText و setImageResource
@Override public View getView(int position, View convertView, ViewGroup parent) { Model current = getItem(position); LayoutInflater layoutInflater = LayoutInflater.from(getContext()); convertView = layoutInflater.inflate(R.layout.item, parent, false); ((TextView) convertView.findViewById(R.id.textView)).setText(current.getName()); ((ImageView) convertView.findViewById(R.id.image)).setImageResource(current.getImage()); return convertView;}
ملاحظة مهمة:
ViewHolder هي طريقة ليست اجبارية لأستخدامها كما في RecyclerView لكن يفضل إستخدامها لجعل التطبيق يعمل بكفاءة أكثر و أسرع من خلال أنها تحفظ id كل View. بهذه الطريقه لا يحتاج Adapter أن يستدعي findViewById() في كل مرة و يحدث بطئ للتطبيق.
. سوف نستخدمها الآن فقط لتوضيح الفكرة ولك حرية اختيار أي طريقة تريد ، لكن شخصياَ أفضل استخدام ViewHolder.
الآن نحذف الكود السابق في ميثود getView()
و نقوم بإنشاء inner class و نعرف به View المستخدمة بملف xml
myAdapter.java public static class ViewHolder { TextView text; ImageView image; }
في ميثود getView
نضع شرط if بحيث نتحقق هل View جديدة او تم عملها سابقاَ، اذا جديدة سوف يقوم بإنشائها ثم نستخدم ميثود setTag() وظيفتها تحفظ View لأعادة استخدامها لاحقاَ.
أما اذا view موجودة فنستخدم getTag لأخذ views و استخدامها.
و أخيراَ نرفق القيم في views
@Override public View getView(int position, View convertView, ViewGroup parent) { Model current = getItem(position); ViewHolder viewHolder = new ViewHolder(); if(convertView==null) { convertView = LayoutInflater.from(getContext()).inflate(R.layout.item, parent, false); viewHolder.text = convertView.findViewById(R.id.textView); viewHolder.image = convertView.findViewById(R.id.image); convertView.setTag(viewHolder); }else{ convertView.getTag(); } viewHolder.text.setText(current.getName()); viewHolder.image.setImageResource(current.getImage()); return convertView; }
ننتقل الآن MainActivity.java
نربط ListView مع ملف الجافا بواسطة ميثود findViewById ثم نقوم بإنشاء ArrayList من نوع Model ونضيف القيم بها
أخيراً نستدعي setAdapter() لعرض البيانات في ListView
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ListView listView = findViewById(R.id.listView); List<Model> list= new ArrayList<>(); list.add(new Model("thekra", R.drawable.green)); list.add(new Model("dev", R.drawable.color)); myAdapter adapter = new myAdapter(getApplicationContext(), list); listView.setAdapter(adapter); } }
اتمنى وفقت بالشرح,
و السلام عليكم ورحمه الله وبركاته.
لايوجد لديك حساب في عالم البرمجة؟
تحب تنضم لعالم البرمجة؟ وتنشئ عالمك الخاص، تنشر المقالات، الدورات، تشارك المبرمجين وتساعد الآخرين، اشترك الآن بخطوات يسيرة !