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

Cách hiển thị ImageView trong EditText khi đang nhập text (TextWatcher)

Giới thiệu

Bài viết minh họa cách động态 thay đổi icon (drawable) của EditText dựa trên độ dài text nhập vào, sử dụng TextWatcher. Ví dụ: hiện icon khi nhập ≥ 3 ký tự.

Các bước thực hiện

Bước 1: Tạo project mới

Android Studio → File → New Project → Empty Activity.

Bước 2: Tạo background bo góc (res/drawable/bg_edittext_rounded.xml)

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="https://schemas.android.com/apk/res/android">
    <solid android:color="#FFFFFF" />
    <stroke android:width="1dp" android:color="#2F6699" />
    <corners android:radius="10dp" />
</shape>

Bước 3: Chuẩn bị icon (res/drawable/ic_custom.xml hoặc ic_custom.png)

Đặt icon muốn hiển thị khi đủ điều kiện vào res/drawable/.

Bước 4: Giao diện (res/layout/activity_main.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:gravity="center"
    android:layout_marginTop="30dp"
    android:padding="16dp">

    <EditText
        android:id="@+id/etInput"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginHorizontal="16dp"
        android:paddingVertical="12dp"
        android:paddingHorizontal="16dp"
        android:background="@drawable/bg_edittext_rounded"
        android:hint="Nhập ít nhất 3 ký tự..."
        android:drawableStart="@android:drawable/ic_menu_search"
        android:drawablePadding="12dp" />

</LinearLayout>

Bước 5: Logic TextWatcher (MainActivity.kt)

package com.example.dynamicedittexticon

import android.graphics.drawable.Drawable
import android.os.Build
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

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

        // Load drawable một lần
        val iconDrawable: Drawable = ContextCompat.getDrawable(this, R.drawable.ic_custom)!!
            .apply { setBounds(0, 0, 48, 48) } // Set size 48x48 px

        etInput.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
                // Không cần xử lý
            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                val length = s?.length ?: 0
                if (length >= 3) {
                    // Hiện icon custom ở bên trái (start)
                    etInput.setCompoundDrawablesRelativeWithIntrinsicBounds(iconDrawable, null, null, null)
                } else {
                    // Trở về icon mặc định (search)
                    etInput.setCompoundDrawablesRelativeWithIntrinsicBounds(
                        ContextCompat.getDrawable(this@MainActivity, android.R.drawable.ic_menu_search), null, null, null)
                }
            }

            override fun afterTextChanged(s: Editable?) {
                // Không cần xử lý
            }
        })
    }
}

Giải thích các phương thức setCompoundDrawables

  • setCompoundDrawables(left, top, right, bottom): Cố định Left/Right (không RTL-aware).
  • setCompoundDrawablesRelative(start, top, end, bottom): RTL-aware (khuyên dùng). start = trái trong LTR, phải trong RTL.
  • setCompoundDrawablesRelativeWithIntrinsicBounds(...): Tự động dùng kích thước intrinsic của drawable, không cần setBounds thủ công.

Cách dùng với TextInputLayout (Material Design)

<com.google.android.material.textfield.TextInputLayout
    android:id="@+id/tilInput"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="Nhập text"
    app:endIconMode="custom"
    app:endIconDrawable="@drawable/ic_custom">

    <com.google.android.material.textfield.TextInputEditText
        android:id="@+id/etInput"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</com.google.android.material.textfield.TextInputLayout>
// Code Kotlin
tilInput.endIconView.setOnClickListener { /* Xử lý click */ }
// Hoặc ẩn/hiện endIcon:
tilInput.isEndIconVisible = (etInput.text.length >= 3)

Lưu ý

    Luôn setBounds cho drawable nếu dùng setCompoundDrawables (không phải RelativeWithIntrinsicBounds).
  • Drawable size nên phù hợp (24-32dp thường dùng).
  • TextWatcher gọi rất nhiều lần, tránh tạo object mới trong onTextChanged.
  • Dùng setCompoundDrawablesRelative để hỗ trợ RTL (tiếng Ả Rập, Hebrew).