You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin中重写performClick()实现EditText左侧清除图标遇问题

在Kotlin中给EditText添加左侧清除图标并正确重写performClick()方法

嘿,我来帮你搞定这个问题!首先说下你提到的Kotlin识别不了performClick()的情况——其实这个方法是View类自带的,肯定能识别,大概率是代码里的小错误导致的。下面我给你一套完整的实现方案,包含自定义EditText、触摸事件处理和正确重写performClick()的方式:

第一步:自定义ClearableEditText类

我们直接自定义一个EditText子类,把清除图标的逻辑、触摸判断和performClick()重写都封装进去,这样复用性也强:

import android.content.Context
import android.text.Editable
import android.text.TextWatcher
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import androidx.appcompat.widget.AppCompatEditText
import androidx.core.content.ContextCompat

class ClearableEditText @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = android.R.attr.editTextStyle
) : AppCompatEditText(context, attrs, defStyleAttr) {

    init {
        // 初始化左侧清除图标(如果布局里没设置的话)
        val clearIcon = ContextCompat.getDrawable(context, R.drawable.ic_clear)
        setCompoundDrawablesWithIntrinsicBounds(clearIcon, null, null, null)
        compoundDrawablePadding = resources.getDimensionPixelSize(R.dimen.drawable_padding)
        
        // 默认隐藏图标,只有输入内容时显示
        hideClearIcon()
        
        // 监听文本变化,自动切换图标显示状态
        addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
            
            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                if (!s.isNullOrEmpty()) showClearIcon() else hideClearIcon()
            }
            
            override fun afterTextChanged(s: Editable?) {}
        })
    }

    private fun showClearIcon() {
        setCompoundDrawablesWithIntrinsicBounds(
            ContextCompat.getDrawable(context, R.drawable.ic_clear),
            null, null, null
        )
    }

    private fun hideClearIcon() {
        setCompoundDrawablesWithIntrinsicBounds(null, null, null, null)
    }

    override fun onTouch(v: View?, event: MotionEvent?): Boolean {
        event?.let {
            if (it.action == MotionEvent.ACTION_UP) {
                // 获取左侧的Drawable
                val leftDrawable = compoundDrawables[0]
                leftDrawable?.let { drawable ->
                    // 计算可触摸的图标区域宽度(图标宽度+内边距)
                    val touchableWidth = drawable.intrinsicWidth + compoundDrawablePadding
                    // 判断触摸点是否在图标区域内
                    if (it.rawX <= touchableWidth) {
                        // 触发performClick()执行清空逻辑
                        performClick()
                        return true
                    }
                }
            }
        }
        // 交给父类处理其他触摸事件
        return super.onTouch(v, event)
    }

    override fun performClick(): Boolean {
        // 这里就是点击清除图标后的逻辑:清空EditText内容
        text?.clear()
        // 必须调用super.performClick(),确保触发系统的点击回调,满足无障碍要求
        super.performClick()
        return true
    }
}

第二步:布局中使用自定义EditText

在你的XML布局里直接用这个自定义类就行:

<com.yourpackage.ClearableEditText
    android:id="@+id/et_email"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="请输入邮箱"
    android:inputType="textEmailAddress"
    android:drawablePadding="8dp"/>

为什么你的代码可能出问题?

你提到的Kotlin识别不了performClick(),还有触摸事件的问题,大概率是这两个原因:

  1. 调用对象错误:如果你是在Activity里调用et_email.performClick(),得确保et_email是EditText的实例(或者我们自定义的ClearableEditText),不会是其他View类型。
  2. 触摸事件的super调用错误:你原来的代码里写了super.onTouchEvent(event),但在onTouch()回调里应该调用super.onTouch(v, event),这是View.OnTouchListener的正确写法,写错的话会导致触摸事件处理异常。

额外注意点

  • 一定要在重写的performClick()里调用super.performClick(),这不仅能触发OnClickListener的回调,还能满足Android无障碍服务的要求,让屏幕阅读器能识别这个点击操作。
  • 通过TextWatcher监听文本变化,自动显示/隐藏清除图标,用户体验会更好,没有内容的时候图标不会显示占位。

内容的提问来源于stack exchange,提问作者Sergio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:55:07