ListView: คืออะไร รายการอย่างง่ายในแอปพลิเคชัน Android

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-02-23 เวลาอ่าน: 8 นาที

ListView เป็นคอมโพเนนต์พื้นฐานของ Android สำหรับแสดงรายการแนวตั้ง ตั้งแต่ API 1 (Android 1.0) ListView สร้างรายการของไอเท็มโดยใช้ ArrayAdapter และรองรับเค้าโครงเซลล์ที่กำหนดเอง มาทำความเข้าใจว่า ListView คืออะไร วิธีการกำหนดค่า และข้อผิดพลาดที่คอมโพเนนต์เก่าแต่ยังคงใช้งานนี้ซ่อนอยู่ ที่ IT Sectr เราพบ ListView ในโปรเจกต์เดิมและรักษาความเข้ากันได้ย้อนหลังกับ Android 4.4 สำหรับการเปรียบเทียบกับทางเลือกสมัยใหม่อ่าน บทความเกี่ยวกับ RecyclerView

ประเด็นสำคัญ

  • ListView เป็นคอมโพเนนต์ Android SDK ในตัวสำหรับรายการแนวตั้ง เปิดตัวใน Android 1.0
  • ArrayAdapter เป็นอะแดปเตอร์มาตรฐานสำหรับเชื่อมโยงอาร์เรย์ข้อมูลกับ ListView ผ่าน toString() หรือเค้าโครงที่กำหนดเอง
  • SimpleAdapter เป็นอะแดปเตอร์สำหรับรายการจากข้อมูล Map สะดวกสำหรับหน้าจอเรียบง่ายที่ไม่มี ViewModel
  • onItemClickListener เป็นตัวจัดการคลิกในตัวที่ไม่ต้องการการใช้งานเพิ่มเติมในอะแดปเตอร์
  • convertView เป็นกลไกการนำ View กลับมาใช้ใหม่ใน ListView ที่นักพัฒนาต้องดำเนินการด้วยตนเอง (คล้ายกับ ViewHolder)

ListView ใน Android คืออะไร?

ListView คือ ViewGroup จากแพ็คเกจ android.widget ที่ออกแบบมาเพื่อแสดงรายการไอเท็มที่เลื่อนได้ ListView ใช้งานรูปแบบ AdapterView: ข้อมูลจะถูกส่งผ่านอะแดปเตอร์ (Adapter) ซึ่งแปลงไอเท็มข้อมูลเป็น Views ที่แสดงบนหน้าจอ ListView มีอยู่ใน Android SDK ตั้งแต่เวอร์ชันแรก (API 1) และไม่ต้องใช้ไลบรารีเพิ่มเติม

สถาปัตยกรรม ของ ListView ง่ายกว่า RecyclerView: LayoutManager ในตัว (เลื่อนแนวตั้งเท่านั้น) ไม่มีแอนิเมชันการเปลี่ยนแปลง ตัวแบ่งถูกตั้งค่าผ่านแอตทริบิวต์ XML android:divider ListView เพิ่ม OverScrollView และการเน้นโฟกัสโดยอัตโนมัติ ซึ่งช่วยทำให้การสร้างต้นแบบง่ายขึ้น ตามข้อมูลของ Statista (2025) ประมาณ 15% ของแอป Android ใน 100 อันดับแรกของ Play Store ยังคงมี ListView — ส่วนใหญ่เป็นโปรเจกต์เดิมที่มีการสนับสนุนน้อยที่สุด

ประวัติและความเกี่ยวข้อง

ListView เป็นคอมโพเนนต์รายการหลักใน Android ตั้งแต่ปี 2008 ถึง 2014 เมื่อ RecyclerView ถูกนำเสนอที่ Google I/O 2014 แม้จะเลิกใช้บางส่วน (soft-deprecated) แต่ ListView ยังคงใช้ได้ใน Android ทุกรุ่นและไม่ได้ถูกทำเครื่องหมายเป็น @Deprecated ใน SDK API 35 หากโปรเจกต์ของคุณรองรับ Android 4.4 (API 19) และต่ำกว่า ListView เป็นตัวเลือกในตัวเดียวเนื่องจาก RecyclerView ต้องใช้ AndroidX และการพึ่งพา Gradle

ประเภทของอะแดปเตอร์: ArrayAdapter และ SimpleAdapter

ArrayAdapter เป็นอะแดปเตอร์ที่ได้รับความนิยมมากที่สุดสำหรับ ListView โดยรับ List<T> และเค้าโครงสำหรับแต่ละไอเท็ม โดยค่าเริ่มต้น ArrayAdapter เรียก toString() บนแต่ละออบเจ็กต์และแสดงข้อความใน simple_list_item_1 (TextView เดียว) สำหรับการแสดงผลแบบกำหนดเอง คุณต้องแทนที่ getView() หรือส่งเค้าโครงที่กำหนดเองไปยังคอนสตรักเตอร์

kotlin
// ListView กับ ArrayAdapter (ข้อความอย่างง่าย)
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>> และอาร์เรย์ from/to สำหรับเชื่อมโยงคีย์ Map กับ ID ของวิดเจ็ตในเค้าโครง SimpleAdapter สะดวกสำหรับต้นแบบด่วนเมื่อไม่ต้องการคลาสอะแดปเตอร์แยกต่างหาก ข้อเสียคือขาดการพิมพ์ที่ปลอดภัยและความซับซ้อนกับตรรกะที่กำหนดเอง

xml
<!-- เค้าโครง 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>

การสร้างอะแดปเตอร์แบบกำหนดเองด้วย ViewHolder

อะแดปเตอร์ที่กำหนดเอง สำหรับ ListView จะแทนที่เมธอด getView() ซึ่ง RecyclerView แบ่งเป็น onCreateViewHolder + onBindViewHolder ใน ListView ทั้งสองขั้นตอนรวมกัน ดังนั้นนักพัฒนาต้องดำเนินการรูปแบบ ViewHolder อย่างอิสระผ่าน convertView (View ที่ใช้ซ้ำได้) และเมธอด setTag()

kotlin
// โมเดลข้อมูล
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 ไอเท็ม ViewHolder ด้วย view.tag เป็นการเพิ่มประสิทธิภาพที่จำเป็นสำหรับ ListView ที่มีเค้าโครงแบบกำหนดเอง

ข้อจำกัดของ ListView: ทำไม Google แนะนำ RecyclerView

ListView มีข้อจำกัดทางสถาปัตยกรรมสี่ประการที่ Google แก้ไขใน RecyclerView: (1) แนวตั้งเท่านั้น — ไม่มีกริด รายการแนวนอน หรือแบบเรียงซ้อน; (2) ไม่มีการแจ้งเตือนแบบละเอียด — การเปลี่ยนแปลงข้อมูลใด ๆ จะทำให้วาดใหม่ทั้งหมดผ่าน notifyDataSetChanged() ทำให้เกิดการกระตุก; (3) ไม่มีแอนิเมชันการเพิ่ม/ลบไอเท็มในตัว; (4) ไม่มีการแยกหน้าที่ — LayoutManager ในตัว ItemAnimator ไม่มี

xml
<!-- 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+ ไอเท็ม ความแตกต่างจะเห็นได้ชัด: ListView เริ่ม FPS ตกเนื่องจากขาดการคำนวณ diff และ ViewHolder ที่ถูกบังคับ สำหรับรายการที่อัปเดตบ่อย (แชท ฟีด บันทึก) ListView ไม่เหมาะสม — ใช้ RecyclerView กับ Paging 3 ที่ IT Sectr เราย้าย ListView ไปยัง RecyclerView เมื่อทำงานกับหน้าจอเดิมที่มีมากกว่า 50 ไอเท็ม

การกำหนดค่า ListView ผ่านแอตทริบิวต์ XML

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/dp1dp
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 vs RecyclerView: การเปรียบเทียบคุณสมบัติ

การเลือก ระหว่าง ListView และ RecyclerView ขึ้นอยู่กับความต้องการของโปรเจกต์ RecyclerView เป็นมาตรฐานสมัยใหม่ แต่ ListView อาจเหมาะสมสำหรับหน้าจอเรียบง่ายที่มีค่าใช้จ่ายในการบำรุงรักษาโค้ดเดิมน้อยที่สุด การเปรียบเทียบพารามิเตอร์หลักทั้งหมด:

พารามิเตอร์ListViewRecyclerView
ขนาดไลบรารีในตัวใน SDK (≈60 KB)AndroidX (≈300 KB พร้อมการพึ่งพา)
เวอร์ชันขั้นต่ำAPI 1API 14 (ผ่าน AndroidX)
ทิศทางแนวตั้งเท่านั้นแนวตั้ง แนวนอน กริด แบบเรียงซ้อน
ViewHolderดำเนินการด้วยตนเองจำเป็นตามสถาปัตยกรรม
แอนิเมชันเฉพาะการเปลี่ยนแบบเฟดDefaultItemAnimator (add, remove, move, change)
การอัปเดตแบบละเอียดไม่ (เฉพาะ notifyDataSetChanged)notifyItemInserted/Removed/Changed
ตัวฟังคลิกonItemClickListener (ในตัว)ผ่าน ViewHolder (ไม่มีในตัว)
ประสิทธิภาพเพียงพอสำหรับรายการสูงสุด 50 ไอเท็ม60 FPS ที่เสถียรสำหรับ 1000+ ไอเท็ม

สรุป: สำหรับโปรเจกต์ใหม่ ใช้ RecyclerView ปล่อย ListView ไว้ในโค้ดเดิมที่การย้ายข้อมูลมีค่าใช้จ่ายสูงเกินไปเท่านั้น ตามแนวทาง Material Design 3 (2026) รายการทุกความซับซ้อนควรใช้ RecyclerView เพื่อให้เป็นไปตามมาตรฐานประสิทธิภาพและการเข้าถึงที่ทันสมัย

คำถามที่พบบ่อย

ListView ถูกเลิกใช้แล้วหรือไม่?

ListView ไม่ได้ถูกทำเครื่องหมายเป็น @Deprecated ใน Android SDK API 35 แต่ Google ไม่แนะนำให้ใช้ในโปรเจกต์ใหม่ (soft-deprecated) คอมโพเนนต์ยังคงทำงานได้ใน Android ทุกรุ่น RecyclerView เป็นตัวแทนอย่างเป็นทางการตั้งแต่ปี 2014 หากคุณเริ่มโปรเจกต์ใหม่ — เลือก RecyclerView หากคุณดูแลโปรเจกต์ที่มีอยู่ — ListView จะทำงานต่อไปโดยไม่เปลี่ยนแปลง

วิธีเพิ่ม header/footer ให้ ListView?

ListView รองรับเมธอด addHeaderView(View, Object, boolean) และ addFooterView(View, Object, boolean) ส่วนหัวและส่วนท้ายจะถูกเพิ่มในรายการไอเท็มทั่วไปแต่ไม่ได้มีส่วนร่วมในอะแดปเตอร์ — จะแสดงที่จุดเริ่มต้นและจุดสิ้นสุดของรายการเสมอ สำคัญ: เพิ่ม header/footer ก่อนตั้งค่าอะแดปเตอร์ (setAdapter()) มิฉะนั้นจะไม่ถูกรวม หลังจากเพิ่ม header แล้ว ID ตำแหน่งของไอเท็มจะเลื่อนตามจำนวนส่วนหัว

ทำไม ListView ไม่เลื่อนภายใน ScrollView?

ทั้ง ListView และ ScrollView จัดการท่าทางแนวตั้ง ซึ่งสร้างความขัดแย้ง: ScrollView ภายนอกดักจับการเลื่อน และ ListView ไม่เลื่อน วิธีแก้ไข: (1) อย่าวาง ListView ซ้อนใน ScrollView — ใช้ RecyclerView กับ NestedScrollingChild, (2) แทนที่ ScrollView ด้วย NestedScrollView (API 21+), (3) ใช้ ListView ที่มีความสูงคงที่ (android:layout_height="...dp") ภายใน ScrollView แต่จะทำให้การปรับเปลี่ยนเสีย

วิธีล้าง ListView และอัปเดตข้อมูล?

การล้างข้อมูลใน ListView ขึ้นอยู่กับประเภทของอะแดปเตอร์ สำหรับ ArrayAdapter: adapter.clear() และ adapter.addAll(newList) ตามด้วย adapter.notifyDataSetChanged() สำหรับอะแดปเตอร์ที่กำหนดเอง: อัปเดตรายการข้อมูลและเรียก notifyDataSetChanged() หมายเหตุ: listView.invalidateViews() วาด Views ใหม่เท่านั้นแต่ไม่อัปเดตข้อมูล เปลี่ยนข้อมูลผ่านอะแดปเตอร์เสมอ ไม่ใช่โดยตรง

วิธีเปลี่ยนความสูงของไอเท็ม ListView?

ความสูงของไอเท็ม ListView ถูกกำหนดในเค้าโครงของไอเท็ม หากเค้าโครงใช้ layout_height="wrap_content" ความสูงจะปรับตามเนื้อหา สำหรับความสูงคงที่สำหรับไอเท็มทั้งหมด ให้ใช้อะแดปเตอร์ที่กำหนดเองซึ่งตั้งค่า LayoutParams ใน getView(): view.layoutParams.height = resources.getDimensionPixelSize(R.dimen.itemHeight) สำหรับความสูงที่แตกต่างกัน ให้ใช้ RecyclerView ที่มีประเภทวิวต่างกัน

สรุป

  • ListView เป็นคอมโพเนนต์ SDK Android พื้นฐานสำหรับรายการแนวตั้ง ตั้งแต่ API 1
  • ArrayAdapter เป็นอะแดปเตอร์ที่ง่ายที่สุดสำหรับรายการสตริง สำหรับเค้าโครงที่กำหนดเองต้องแทนที่ getView()
  • ViewHolder ใน ListView ถูกดำเนินการด้วยตนเองผ่าน convertView และ view.tag — ข้อกำหนดประสิทธิภาพที่จำเป็น
  • ListView รองรับ choiceMode (single/multiple), header/footer, fastScroll และ android:entries โดยไม่ต้องใช้อะแดปเตอร์
  • ข้อจำกัดของ ListView: แนวตั้งเท่านั้น ไม่มีแอนิเมชัน วาดใหม่ทั้งหมดเมื่อมีการเปลี่ยนแปลงใด ๆ
  • ListView ไม่ได้ถูกทำเครื่องหมายว่าเลิกใช้แล้ว แต่ Google แนะนำ RecyclerView สำหรับโปรเจกต์ใหม่ทั้งหมด
  • สำหรับรายการสูงสุด 50 ไอเท็ม ListView เพียงพอ สำหรับสิ่งที่ซับซ้อนกว่านั้น — ใช้ RecyclerView

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม