Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

วิธีวาง ListView ใน ScrollView โดยไม่หดตัวใน Android ด้วย Kotlin

ภาพรวม

ตัวอย่างนี้สาธิตวิธีแก้ปัญหา ListView หดตัว (Collapse) เมื่อวางอยู่ใน ScrollView โดยคำนวณความสูงรวมของ ListView และตั้งค่า LayoutParams ให้เต็มความสูง

ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่

เปิด Android Studio เลือก File → New Project

ขั้นตอนที่ 2: Layout (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    android:fillViewport="true"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Content above ListView"
            android:textSize="18sp"
            android:textStyle="bold"
            android:padding="16dp" />

        <ListView
            android:id="@+id/listView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="Content below ListView"
            android:textSize="18sp"
            android:textStyle="bold"
            android:padding="16dp" />

    </LinearLayout>

</ScrollView>

ขั้นตอนที่ 3: MainActivity.kt

import android.os.Bundle
import android.widget.ArrayAdapter
import android.widget.ListView
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
    private val listViewArray = arrayOf(
        "ONE", "TWO", "THREE", "FOUR", "FIVE", 
        "SIX", "SEVEN", "EIGHT", "NINE", "TEN",
        "ELEVEN", "TWELVE", "THIRTEEN", "FOURTEEN", "FIFTEEN", "SIXTEEN"
    )

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        title = "KotlinApp"

        val listView = findViewById<ListView>(R.id.listView)
        listView.adapter = ArrayAdapter(
            this, 
            android.R.layout.simple_list_item_1, 
            listViewArray
        )

        // เรียกฟังก์ชันคำนวณความสูงหลังจาก setAdapter
        ListHelper.setListViewHeightBasedOnItems(listView)
    }
}

ขั้นตอนที่ 4: Helper Class (ListHelper.kt)

import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.widget.ListAdapter
import android.widget.ListView

object ListHelper {
    fun setListViewHeightBasedOnItems(listView: ListView) {
        val listAdapter = listView.adapter ?: return

        var totalHeight = 0
        val desiredWidth = View.MeasureSpec.makeMeasureSpec(
            listView.width, 
            View.MeasureSpec.AT_MOST
        )

        for (i in 0 until listAdapter.count) {
            val listItem = listAdapter.getView(i, null, listView)
            listItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED)
            totalHeight += listItem.measuredHeight
        }

        // เพิ่มความสูงของ Divider
        val params = listView.layoutParams
        params.height = totalHeight + (listView.dividerHeight * (listAdapter.count - 1))
        listView.layoutParams = params
        listView.requestLayout()

        Log.d("ListHelper", "Total ListView height: $totalHeight px")
    }
}

วิธีแก้ปัญหาที่ดีกว่า (Best Practice)

ไม่ควรวาง ListView/RecyclerView ใน ScrollView เพราะ:

  • Scrolling behavior จะขัดแย้งกัน (Nested Scrolling)
  • Performance แย่ (View recycling ไม่ทำงาน)
  • Memory usage สูง

แนะนำ: ใช้ RecyclerView แบบ Nested Scrolling

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recyclerView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:nestedScrollingEnabled="false" />

หรือใช้ NestedScrollView + RecyclerView (API 21+)

<androidx.core.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true">

    <LinearLayout ... >
        <!-- Header content -->
        
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:nestedScrollingEnabled="false" />
            
        <!-- Footer content -->
    </LinearLayout>

</androidx.core.widget.NestedScrollView>

ขั้นตอนที่ 5: Manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
    package="com.example.listviewinscrollview">
    <application ... >
        <activity android:name=".MainActivity"> ... </activity>
    </application>
</manifest>

การทดสอบ

รันแอป จะเห็น ListView แสดงเต็มรายการทั้งหมด 16 ไอเท็ม พร้อม Header และ Footer เลื่อนได้ปกติ