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 অন্তর্নির্মিত (শুধু উল্লম্ব স্ক্রোলিং), পরিবর্তন অ্যানিমেশন অনুপস্থিত, বিভাজক android:divider XML বৈশিষ্ট্যের মাধ্যমে সেট করা হয়। ListView স্বয়ংক্রিয়ভাবে OverScrollView এবং ফোকাস হাইলাইটিং যোগ করে, যা প্রোটোটাইপিং সহজ করে। Statista (2025) অনুসারে, Play Store-এর শীর্ষ 100-এ প্রায় 15% Android অ্যাপে এখনও 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 কীগুলিকে লেআউটে উইজেট ID-তে বাঁধাই করার জন্য 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-এ, উভয় ধাপ একত্রিত, তাই ডেভেলপারকে স্বাধীনভাবে ViewHolder প্যাটার্ন বাস্তবায়ন করতে হবে convertView (পুনর্ব্যবহারযোগ্য View) এবং setTag() পদ্ধতি ব্যবহার করে।
// ডেটা মডেল
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+ আইটেমযুক্ত তালিকায় পিছিয়ে যাওয়ার কারণ হয়। view.tag-সহ ViewHolder কাস্টম লেআউট-সহ ListView-এর জন্য একটি বাধ্যতামূলক অপ্টিমাইজেশন।
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) পদ্ধতি সমর্থন করে। হেডার এবং ফুটার আইটেমের সাধারণ তালিকায় যোগ করা হয় কিন্তু অ্যাডাপ্টারে অংশ নেয় না — তারা সবসময় তালিকার শুরুতে এবং শেষে প্রদর্শিত হয়। গুরুত্বপূর্ণ: অ্যাডাপ্টার সেট করার আগে header/footer যোগ করুন (setAdapter()), অন্যথায় সেগুলি বিবেচনায় নেওয়া হবে না। হেডার যোগ করার পর, আইটেম অবস্থান ID হেডারের সংখ্যা দ্বারা স্থানান্তরিত হয়।
ListView এবং ScrollView উভয়ই উল্লম্ব অঙ্গভঙ্গি পরিচালনা করে, যা একটি দ্বন্দ্ব তৈরি করে: বাইরের ScrollView স্ক্রোলিং আটকায়, এবং ListView স্ক্রোল করে না। সমাধান: (1) ScrollView-এর ভিতরে ListView নেস্ট করবেন না — 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 আইটেমের উচ্চতা আইটেম লেআউট XML-এ সেট করা হয়। যদি লেআউট layout_height="wrap_content" ব্যবহার করে, তাহলে উচ্চতা বিষয়বস্তু অনুযায়ী সামঞ্জস্য হয়। সমস্ত আইটেমের জন্য নির্দিষ্ট উচ্চতার জন্য, একটি কাস্টম অ্যাডাপ্টার ব্যবহার করুন যা getView()-এ LayoutParams সেট করে: view.layoutParams.height = resources.getDimensionPixelSize(R.dimen.itemHeight)। বিভিন্ন উচ্চতার জন্য, বিভিন্ন ভিউ প্রকার-সহ RecyclerView ব্যবহার করুন।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।