自定义EditText
自定义View练习,用Kotlin实现一个带删除功能的EditText。
实现代码:
自定义属性:
只有一个自定义属性,用于设置删除按钮的图标
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="EditTextWithClear">
<attr name="clearIcon" format="reference"/>
</declare-styleable>
</resources>
关键代码:EditTextWithClear.kt
代码中有详细注释
package com.example.customedittext
import android.content.Context
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.view.MotionEvent
import androidx.core.content.ContextCompat
/**
* 自定义EditText
*/
class EditTextWithClear @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : androidx.appcompat.widget.AppCompatEditText(context, attrs, defStyleAttr) {
private var iconDrawable:Drawable? = null;
//在构造方法执行之后调用
init {
//获取自定义属性
context.theme.obtainStyledAttributes(
attrs,
R.styleable.EditTextWithClear,
0,0
).apply {
try {
//得到设置的自定义属性值
val iconId = getResourceId(R.styleable.EditTextWithClear_clearIcon,0)
if (iconId != 0) {
iconDrawable = ContextCompat.getDrawable(context,iconId)
}
}finally {
//及时回收
recycle()
}
}
}
//监听内容改变
override fun onTextChanged(
text: CharSequence?,
start: Int,
lengthBefore: Int,
lengthAfter: Int
) {
super.onTextChanged(text, start, lengthBefore, lengthAfter)
toggleClearIcon()
}
/**
* 触摸事件监听
* 判定是否触摸到clear图标
*/
override fun onTouchEvent(event: MotionEvent?): Boolean {
event?.let { e ->
iconDrawable?.let {
//判断触摸的区域是否在图标位置
if(e.action == MotionEvent.ACTION_UP //当触摸抬起时
&& e.x > width - it.intrinsicWidth
&& e.x < width
&& e.y > height / 2 - it.intrinsicHeight / 2
&& e.y < height /2 + it.intrinsicHeight / 2
){
text?.clear()
}
}
}
//消除onTouchEvent()的警告
performClick()
return super.onTouchEvent(event)
}
//焦点改变监听
override fun onFocusChanged(focused: Boolean, direction: Int, previouslyFocusedRect: Rect?) {
super.onFocusChanged(focused, direction, previouslyFocusedRect)
toggleClearIcon()
}
override fun performClick(): Boolean {
return super.performClick()
}
/*
clear图标的状态切换
*/
private fun toggleClearIcon(){
val icon = if(text?.isNotEmpty() == true && isFocused) iconDrawable else null
/**在上下左右设置图标,不需要的地方设置为null,使用图标原本固有宽高
使用setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom),
需要给Drawable设置setBounds(x,y,width,height)**/
setCompoundDrawablesRelativeWithIntrinsicBounds(null,null,icon,null);
}
}
布局代码:
布局中有三种EditText
1、原始EditText
2、自定义EditTextWithClear
3、新的控件TextInputLayout
TextInputLayout也有删除功能,是一个更加美观的EditText
app:endIconMode=“clear_text” 该属性设置末尾icon的功能
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.example.customedittext.EditTextWithClear
android:id="@+id/editTextWithClear"
style="@style/Widget.AppCompat.EditText"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:hint="@string/a_custom_edittext"
app:clearIcon="@drawable/ic_baseline_clear_24"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.478"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.418" />
<EditText
android:id="@+id/editTextTextPersonName"
style="@style/Widget.AppCompat.EditText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:hint="EdiText"
android:inputType="textPersonName"
app:layout_constraintBottom_toTopOf="@+id/editTextWithClear"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.textfield.TextInputLayout
android:layout_width="200dp"
android:layout_height="wrap_content"
app:endIconMode="clear_text"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editTextWithClear">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="TextInputLayout" />
</com.google.android.material.textfield.TextInputLayout>
</androidx.constraintlayout.widget.ConstraintLayout>