Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Tạo EditText có focus trong ListView trên Android Kotlin

Hướng dẫn này minh họa cách tạo EditText có thể focus (nhập liệu) bên trong ListView trên Android sử dụng Kotlin.

Bước 1: Tạo dự án mới

Mở Android Studio, chọn File → New Project và điền thông tin cần thiết.

Bước 2: Thiết kế giao diện chính (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>

Bước 3: Viết code MainActivity.kt

import androidx.appcompat.app.AppCompatActivity
import android.annotation.SuppressLint
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 java.util.ArrayList

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

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

        listView = findViewById(R.id.listView)
        listView.itemsCanFocus = true
        myAdapter = MyAdapter()
        listView.adapter = myAdapter
    }

    private inner class MyAdapter internal constructor() : BaseAdapter() {
        private var layoutInflater: LayoutInflater =
            getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater

        internal var myItems = ArrayList<String>()
        lateinit var context: Context

        init {
            for (i in 0..6) {
                myItems.add("Caption$i")
            }
            notifyDataSetChanged()
        }

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

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

            if (convertView == null) {
                holder = ViewHolder()
                convertView = layoutInflater.inflate(R.layout.list, null)
                holder.caption = convertView.findViewById(R.id.ItemCaption)
                convertView.tag = holder
            } else {
                holder = convertView.tag as ViewHolder
            }

            holder.caption.setText(myItems[position])
            holder.caption.id = position

            holder.caption.onFocusChangeListener = View.OnFocusChangeListener { v, hasFocus ->
                if (!hasFocus) {
                    val position = v.id
                    val caption = v as EditText
                    myItems[position] = caption.text.toString()
                }
            }

            return convertView
        }
    }

    internal inner class ViewHolder {
        lateinit var caption: EditText
    }
}

Bước 4: Tạo layout item (list.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="match_parent"
    android:orientation="vertical"
    android:paddingStart="4dp">

    <EditText
        android:id="@+id/ItemCaption"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="2dip"
        android:singleLine="true" />

</LinearLayout>

Bước 5: Cấu hình AndroidManifest.xml

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>
</manifest>

Chạy ứng dụng

Kết nối thiết bị, nhấn Run. ListView hiển thị 7 dòng EditText. Người dùng có thể click vào từng dòng để nhập text, nội dung sẽ được lưu vào list khi mất focus.

Các điểm quan trọng

  • android:descendantFocusability="beforeDescendants" - Cho phép child view nhận focus
  • listView.itemsCanFocus = true - Cho phép item trong ListView có focus
  • ViewHolder pattern - Tối ưu hiệu năng, tránh findViewById lặp lại
  • onFocusChangeListener - Lưu dữ liệu khi EditText mất focus
Lưu ý: ListView với EditText dễ gặp vấn đề focus/keyboard. Khuyến nghị dùng RecyclerView cho trường hợp phức tạp.