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(),还有触摸事件的问题,大概率是这两个原因:
- 调用对象错误:如果你是在Activity里调用
et_email.performClick(),得确保et_email是EditText的实例(或者我们自定义的ClearableEditText),不会是其他View类型。 - 触摸事件的super调用错误:你原来的代码里写了
super.onTouchEvent(event),但在onTouch()回调里应该调用super.onTouch(v, event),这是View.OnTouchListener的正确写法,写错的话会导致触摸事件处理异常。
额外注意点
- 一定要在重写的
performClick()里调用super.performClick(),这不仅能触发OnClickListener的回调,还能满足Android无障碍服务的要求,让屏幕阅读器能识别这个点击操作。 - 通过TextWatcher监听文本变化,自动显示/隐藏清除图标,用户体验会更好,没有内容的时候图标不会显示占位。
内容的提问来源于stack exchange,提问作者Sergio
相关产品推荐
相关产品推荐

