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

วิธีสร้าง EditText ที่โฟกัสได้ใน ListView บน Android ด้วย Kotlin

ตัวอย่างนี้สาธิตวิธีทำให้ EditText ภายใน ListItem สามารถโฟกัสและพิมพ์ได้ โดยตั้งค่า android:descendantFocusability="beforeDescendants" ให้ ListView

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

Android Studio → New Project → Empty Activity

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

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    android:padding="4dp"
    tools:context=".MainActivity">

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

</LinearLayout>

ขั้นตอนที่ 3: Layout รายการ (res/layout/list_item.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:paddingStart="4dp">

    <EditText
        android:id="@+id/etItemCaption"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="2dp"
        android:singleLine="true"
        android:hint="Enter text..." />

</LinearLayout>

ขั้นตอนที่ 4: โค้ดหลัก (MainActivity.kt)

import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.EditText
import android.widget.ListView
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
    private lateinit var listView: ListView
    private lateinit var adapter: MyAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        title = "Focusable EditText in ListView"

        listView = findViewById(R.id.listView)
        // 🔑 จุดสำคัญ: อนุญาตให้ Child View โฟกัสได้
        listView.itemsCanFocus = true

        adapter = MyAdapter(this)
        listView.adapter = adapter
    }

    private inner class MyAdapter(private val context: Context) : BaseAdapter() {
        private val inflater: LayoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
        private val items = mutableListOf()

        init {
            // ข้อมูลตัวอย่าง 7 รายการ
            repeat(7) { items.add("Item $it") }
        }

        override fun getCount(): Int = items.size
        override fun getItem(position: Int): Any = items[position]
        override fun getItemId(position: Int): Long = position.toLong()

        override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
            var view = convertView
            val holder: ViewHolder

            if (view == null) {
                holder = ViewHolder()
                view = inflater.inflate(R.layout.list_item, parent, false)
                holder.etCaption = view.findViewById(R.id.etItemCaption)
                view.tag = holder
            } else {
                holder = view.tag as ViewHolder
            }

            // ตั้งค่าข้อความ
            holder.etCaption.setText(items[position])
            holder.etCaption.tag = position // เก็บ position ไว้

            // 🔑 จุดสำคัญ: บันทึกข้อมูลเมื่อโฟกัสหาย (Lost Focus)
            holder.etCaption.setOnFocusChangeListener { v, hasFocus ->
                if (!hasFocus) {
                    val pos = v.tag as Int
                    items[pos] = v.text.toString()
                }
            }

            return view!!
        }

        private class ViewHolder {
            lateinit var etCaption: EditText
        }
    }
}

🔑 จุดสำคัญ 2 อย่าง

  1. ListView XML: android:descendantFocusability="beforeDescendants"
  2. Code: listView.itemsCanFocus = true

⚠️ ข้อควรระวัง

  • Soft Keyboard อาจบัง ListItem → ใช้ android:windowSoftInputMode="adjustPan|adjustResize" ใน Manifest
  • ListView แบบนี้ไม่เหมาะกับรายการเยอะ (Performance) → ควรใช้ RecyclerView แทน
  • ต้องจัดการ Focus แบบ Manual สำหรับการ Scroll

AndroidManifest.xml (Activity Config)

<activity
    android:name=".MainActivity"
    android:windowSoftInputMode="adjustResize">
    ...
</activity>

ทดสอบ

  1. รันแอป → แสดง ListView 7 รายการ แต่ละรายการมี EditText
  2. กดที่ EditText ใดๆ → Keyboard ขึ้น พิมพ์ได้
  3. กด Enter/นอกพื้นที่ → ข้อมูลจะบันทึกลง List อัตโนมัติ