ListView Android کا ایک بنیادی جزو ہے جو عمودی فہرستیں دکھانے کے لیے ہے، API 1 (Android 1.0) سے دستیاب ہے۔ ListView ArrayAdapter کا استعمال کرتے ہوئے آئٹمز کی فہرست بناتا ہے اور کسٹم سیل لے آؤٹ کو سپورٹ کرتا ہے۔ آئیے سمجھتے ہیں کہ ListView کیا ہے، اسے کیسے کنفیگر کریں، اور یہ پرانا لیکن اب بھی استعمال ہونے والا جزو کیا پوشیدہ مسائل رکھتا ہے۔ IT Sectr میں، ہم لیگیسی پروجیکٹس میں ListView کا سامنا کرتے ہیں اور Android 4.4 کے ساتھ پسماندہ مطابقت برقرار رکھتے ہیں۔ جدید متبادل سے موازنہ کے لیے، RecyclerView کے بارے میں مضمون پڑھیں۔
اہم نکات
ListView android.widget پیکیج کا ایک ViewGroup ہے، جو اسکرول ایبل آئٹمز کی فہرست دکھانے کے لیے ڈیزائن کیا گیا ہے۔ ListView AdapterView پیٹرن کو نافذ کرتا ہے: ڈیٹا ایک اڈاپٹر (Adapter) کے ذریعے منتقل کیا جاتا ہے، جو ڈیٹا آئٹمز کو اسکرین پر دکھائے جانے والے Views میں تبدیل کرتا ہے۔ ListView پہلے ورژن (API 1) سے Android SDK میں موجود ہے اور اضافی لائبریریوں کی ضرورت نہیں ہے۔
آرکیٹیکچر ListView کا RecyclerView سے آسان ہے: LayoutManager بلٹ ان ہے (صرف عمودی اسکرولنگ)، تبدیلی اینیمیشن غائب ہیں، جداکنندگان XML خصوصیت android:divider کے ذریعے سیٹ کیے جاتے ہیں۔ ListView خود بخود OverScrollView اور فوکس ہائی لائٹنگ شامل کرتا ہے، جو پروٹوٹائپنگ کو آسان بناتا ہے۔ Statista (2025) کے مطابق، Play Store کے ٹاپ 100 Android ایپس میں سے تقریباً 15% میں اب بھی ListView موجود ہے — زیادہ تر کم سے کم سپورٹ والے لیگیسی پروجیکٹس۔
ListView 2008 سے 2014 تک Android میں بنیادی فہرست کا جزو تھا، جب Google I/O 2014 میں RecyclerView متعارف کرایا گیا۔ جزوی طور پر فرسودہ (soft-deprecated) ہونے کے باوجود، ListView Android کے تمام ورژنز میں دستیاب ہے اور SDK API 35 میں @Deprecated کے طور پر نشان زد نہیں ہے۔ اگر آپ کا پروجیکٹ Android 4.4 (API 19) اور اس سے نیچے کو سپورٹ کرتا ہے، تو ListView واحد بلٹ ان انتخاب ہے کیونکہ RecyclerView کو AndroidX اور Gradle انحصار کی ضرورت ہے۔
ArrayAdapter ListView کے لیے سب سے مقبول اڈاپٹر ہے۔ یہ ہر آئٹم کے لیے ایک List<T> اور ایک لے آؤٹ لیتا ہے۔ ڈیفالٹ طور پر، ArrayAdapter ہر آبجیکٹ پر toString() کال کرتا ہے اور simple_list_item_1 (ایک TextView) میں متن دکھاتا ہے۔ کسٹم ڈسپلے کے لیے، آپ کو getView() کو اوور رائڈ کرنا ہوگا یا کنسٹرکٹر کو کسٹم لے آؤٹ دینا ہوگا۔
// ArrayAdapter کے ساتھ ListView (سادہ متن)
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val countries = listOf(
"روس", "امریکہ", "جرمنی",
"فرانس", "جاپان", "چین", "برازیل"
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val adapter = ArrayAdapter<String>(
this,
android.R.layout.simple_list_item_1,
countries
)
binding.listView.adapter = adapter
// کلک ہینڈلنگ
binding.listView.onItemClickListener =
AdapterView.OnItemClickListener { _, _, position, _ ->
Toast.makeText(this, countries[position], Toast.LENGTH_SHORT).show()
}
}
}
SimpleAdapter Map ڈیٹا سے فہرستوں کے لیے ڈیزائن کیا گیا ہے۔ یہ ایک List<Map<String, Any>> اور لے آؤٹ میں Map کلیدوں کو ویجٹ IDs سے منسلک کرنے کے لیے from/to اری لیتا ہے۔ SimpleAdapter فوری پروٹوٹائپس کے لیے آسان ہے جب علیحدہ اڈاپٹر کلاس کی ضرورت نہ ہو۔ منفی پہلو ٹائپ سیف ٹائپنگ کی کمی اور کسٹم لاجک کے ساتھ پیچیدگی ہے۔
<!-- ListView لے آؤٹ -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@color/divider"
android:dividerHeight="1px"
android:scrollbars="vertical" />
</LinearLayout>
کسٹم اڈاپٹر ListView کے لیے getView() طریقہ کو اوور رائڈ کرتا ہے، جسے RecyclerView onCreateViewHolder + onBindViewHolder میں تقسیم کرتا ہے۔ ListView میں، دونوں مراحل مل جاتے ہیں، اس لیے ڈیولپر کو convertView (دوبارہ استعمال کے قابل View) اور setTag() طریقہ کے ذریعے ViewHolder پیٹرن کو آزادانہ طور پر نافذ کرنا ہوتا ہے۔
// ڈیٹا ماڈل
data class Product(
name: String,
price: String,
imageResId: Int
)
// ViewHolder کے ساتھ کسٹم اڈاپٹر
class ProductAdapter(
context: Context,
private val products: List<Product>
) : ArrayAdapter<Product>(context, 0, products) {
// کیشنگ کے لیے ViewHolder
private class ViewHolder(view: View) {
val nameText: TextView = view.findViewById(R.id.tvName)
val priceText: TextView = view.findViewById(R.id.tvPrice)
val imageView: ImageView = view.findViewById(R.id.ivProduct)
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val view = convertView ?: LayoutInflater.from(context)
.inflate(R.layout.item_product, parent, false)
.also { it.tag = ViewHolder(it) }
val holder = view.tag as ViewHolder
val product = getItem(position)
holder.nameText.text = product.name
holder.priceText.text = product.price
holder.imageView.setImageResource(product.imageResId)
return view
}
}
RecyclerView سے اہم فرق: ListView میں، getView() طریقہ ہر بار جب کوئی آئٹم اسکرین پر ظاہر ہوتا ہے کال کیا جاتا ہے۔ اگر convertView اور ViewHolder استعمال نہ کیے جائیں، تو ہر اسکرول ایک نیا View آبجیکٹ بناتا ہے، جس سے 50+ آئٹمز والی فہرستوں میں میموری لیک اور سست روی ہوتی ہے۔ کسٹم لے آؤٹ والے ListView کے لیے view.tag کے ساتھ ViewHolder ایک لازمی اصلاح ہے۔
ListView میں چار آرکیٹیکچرل حدود ہیں جو Google نے RecyclerView میں ٹھیک کیں: (1) صرف عمودی سمت — کوئی گرڈ، افقی فہرستیں یا جھرن نہیں؛ (2) کوئی دانے دار اطلاع نہیں — ڈیٹا کی کوئی بھی تبدیلی notifyDataSetChanged() کے ذریعے مکمل دوبارہ ڈرائنگ شروع کرتی ہے، جھٹکے کا سبب بنتی ہے؛ (3) آئٹم شامل کرنے/ہٹانے کی کوئی بلٹ ان اینیمیشن نہیں؛ (4) ذمہ داریوں کی کوئی علیحدگی نہیں — LayoutManager بلٹ ان ہے، ItemAnimator غائب ہے۔
<!-- item_product.xml — ListView آئٹم لے آؤٹ -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="12dp">
<ImageView
android:id="@+id/ivProduct"
android:layout_width="56dp"
android:layout_height="56dp"
android:scaleType="centerCrop" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:paddingStart="12dp">
<TextView
android:id="@+id/tvName"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvPrice"
android:textSize="14sp"
android:textColor="@color/price" />
</LinearLayout>
</LinearLayout>
عملی اثرات: 20 آئٹمز تک کی فہرستوں پر، ListView اتنی ہی تیزی سے کام کرتا ہے جتنا RecyclerView۔ 100+ آئٹمز پر، فرق نمایاں ہو جاتا ہے: فرق حسابات اور لازمی ViewHolder کی کمی کی وجہ سے ListView میں FPS گرنا شروع ہو جاتا ہے۔ بار بار اپ ڈیٹ ہونے والی فہرستوں (چیٹ، فیڈ، لاگ) کے لیے ListView موزوں نہیں ہے — Paging 3 کے ساتھ RecyclerView استعمال کریں۔ IT Sectr میں، ہم 50 سے زیادہ آئٹمز والی لیگیسی اسکرینوں پر کام کرتے وقت ListView کو RecyclerView میں منتقل کرتے ہیں۔
ListView بغیر کوڈ کے فوری کنفیگریشن کے لیے XML خصوصیات کا ایک سیٹ فراہم کرتا ہے: android:divider (جداکنندہ رنگ/ڈرایبل)، android:dividerHeight (موٹائی)، android:scrollbars (اسکرول بارز)، android:fastScrollEnabled (ہینڈلر کے ذریعے تیز اسکرول)، android:choiceMode (انتخاب موڈ: singleChoice، multipleChoice)۔ android:entries خصوصیت بغیر اڈاپٹر کے وسائل کی اری (string-array) سے فہرست بھرنے کی اجازت دیتی ہے۔
| خصوصیت | تفصیل | مثال کی قدر |
|---|---|---|
| android:divider | جداکنندہ رنگ یا ڈرایبل | @color/gray_light |
| android:dividerHeight | px/dp میں جداکنندہ موٹائی | 1dp |
| android:entries | وسائل سے سٹرنگ اری | @array/countries |
| android:choiceMode | آئٹم انتخاب موڈ | singleChoice |
| android:fastScrollEnabled | تیز اسکرولنگ | true |
| android:overlapAnchor | پاپ اپ فہرستوں کے لیے اینکر (API 21+) | true |
انتخاب موڈ: choiceMode="singleChoice" RadioButton طرز کو فعال کرتا ہے جہاں منتخب آئٹم ہائی لائٹ ہوتا ہے۔ choiceMode="multipleChoice" — متعدد آئٹمز کے لیے چیک باکسز۔ انتخاب کا ڈیٹا listView.checkedItemPosition یا listView.checkedItemIds کے ذریعے دستیاب ہے۔ اہم: choiceMode کے ساتھ، ListView پس منظر کے لیے StateListDrawable استعمال کرتا ہے — اگر معیاری نیلا ڈیزائن سے مطابقت نہیں رکھتا تو اپنا سلیکٹر سیٹ کریں۔
انتخاب ListView اور RecyclerView کے درمیان پروجیکٹ کی ضروریات پر منحصر ہے۔ RecyclerView جدید معیار ہے، لیکن ListView لیگیسی کوڈ کے کم سے کم دیکھ بھال کے اخراجات والی سادہ اسکرینوں کے لیے جائز ہو سکتا ہے۔ تمام اہم پیرامیٹرز پر موازنہ:
| پیرامیٹر | ListView | RecyclerView |
|---|---|---|
| لائبریری کا سائز | SDK میں بلٹ ان (≈60 KB) | AndroidX (انحصار کے ساتھ ≈300 KB) |
| کم از کم ورژن | API 1 | API 14 (AndroidX کے ذریعے) |
| سمت | صرف عمودی | عمودی، افقی، گرڈ، سیڑھی نما |
| ViewHolder | دستی نفاذ | آرکیٹیکچر کے لحاظ سے لازمی |
| اینیمیشن | صرف فیڈ ٹرانزیشن | DefaultItemAnimator (add, remove, move, change) |
| دانے دار اپ ڈیٹس | نہیں (صرف notifyDataSetChanged) | notifyItemInserted/Removed/Changed |
| کلک لسنر | onItemClickListener (بلٹ ان) | ViewHolder کے ذریعے (بلٹ ان نہیں) |
| کارکردگی | 50 آئٹمز تک کی فہرستوں کے لیے کافی | 1000+ آئٹمز کے لیے مستحکم 60 FPS |
نتیجہ: نئے پروجیکٹس کے لیے، RecyclerView استعمال کریں۔ ListView کو صرف لیگیسی کوڈ میں چھوڑیں جہاں منتقلی غیر معقول طور پر مہنگی ہو۔ Material Design 3 رہنما خطوط (2026) کے مطابق، کسی بھی پیچیدگی کی فہرستوں کو جدید کارکردگی اور رسائی کے معیارات کو پورا کرنے کے لیے RecyclerView استعمال کرنا چاہیے۔
اکثر پوچھے جانے والے سوالات
ListView Android SDK API 35 میں @Deprecated کے طور پر نشان زد نہیں ہے، لیکن Google نئے پروجیکٹس میں اس کے استعمال کی سفارش نہیں کرتا (soft-deprecated)۔ جزو Android کے تمام ورژنز میں فعال رہتا ہے۔ RecyclerView 2014 سے سرکاری متبادل ہے۔ اگر آپ نیا پروجیکٹ شروع کر رہے ہیں — RecyclerView کا انتخاب کریں۔ اگر آپ موجودہ پروجیکٹ کو برقرار رکھ رہے ہیں — ListView بغیر تبدیلی کے کام کرتا رہے گا۔
ListView addHeaderView(View, Object, boolean) اور addFooterView(View, Object, boolean) طریقوں کو سپورٹ کرتا ہے۔ ہیڈر اور فوٹر عام آئٹم فہرست میں شامل کیے جاتے ہیں لیکن اڈاپٹر میں حصہ نہیں لیتے — وہ ہمیشہ فہرست کے شروع اور آخر میں دکھائے جاتے ہیں۔ اہم: اڈاپٹر سیٹ کرنے (setAdapter()) سے پہلے header/footer شامل کریں، ورنہ وہ شامل نہیں ہوں گے۔ ہیڈر شامل کرنے کے بعد، آئٹم پوزیشن IDs ہیڈرز کی تعداد کے مطابق منتقل ہو جاتی ہیں۔
ListView اور ScrollView دونوں عمودی جیسچرز کو ہینڈل کرتے ہیں، جو ایک تصادم پیدا کرتا ہے: بیرونی ScrollView اسکرول کو روک لیتا ہے، اور ListView اسکرول نہیں ہوتا۔ حل: (1) ListView کو ScrollView کے اندر نیسٹ نہ کریں — NestedScrollingChild کے ساتھ RecyclerView استعمال کریں، (2) ScrollView کو NestedScrollView (API 21+) سے بدل دیں، (3) ScrollView کے اندر مقررہ اونچائی (android:layout_height="...dp") کے ساتھ ListView استعمال کریں، لیکن اس سے موافقت ٹوٹ جائے گی۔
ListView میں ڈیٹا صاف کرنا اڈاپٹر کی قسم پر منحصر ہے۔ ArrayAdapter کے لیے: adapter.clear() اور adapter.addAll(newList) پھر adapter.notifyDataSetChanged()۔ کسٹم اڈاپٹر کے لیے: ڈیٹا فہرست کو اپ ڈیٹ کریں اور notifyDataSetChanged() کال کریں۔ نوٹ: listView.invalidateViews() صرف Views کو دوبارہ ڈرا کرتا ہے لیکن ڈیٹا اپ ڈیٹ نہیں کرتا۔ ہمیشہ اڈاپٹر کے ذریعے ڈیٹا تبدیل کریں، براہ راست نہیں۔
ListView آئٹم کی اونچائی آئٹم لے آؤٹ میں سیٹ کی جاتی ہے۔ اگر لے آؤٹ layout_height="wrap_content" استعمال کرتا ہے، تو اونچائی مواد کے مطابق ایڈجسٹ ہوتی ہے۔ تمام آئٹمز کے لیے مقررہ اونچائی کے لیے، ایک کسٹم اڈاپٹر استعمال کریں جو getView() میں LayoutParams سیٹ کرے: view.layoutParams.height = resources.getDimensionPixelSize(R.dimen.itemHeight)۔ مختلف اونچائیوں کے لیے، مختلف ویو ٹائپس کے ساتھ RecyclerView استعمال کریں۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔