目录
一 概述
自定义View可由以下四个方面涵盖。
- 绘图:画布Canvas 画笔Paint
- 交互:触摸TouchEvent 动画Animation
- 性能:onDraw 考虑主线程安全 SurfaceView副线程绘图,不会阻塞主线程
- 封装:尺寸measure 属性attributes
二 实战:带清除按钮的文本输入框
继承于系统的EditText,通过增加监听器也可以实现;但是可复用性不高。
这里做一个可以自定义清除按钮的文本输入框。
2.1 继承EditText
class EditTextWithClear @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : AppCompatEditText(context, attrs,defStyleAttr)
2.2 编写attrs.xml文件设置自定义属性
<declare-styleable name="EditTextWithClear">
<attr name="clearIcon" format="reference"/>
</declare-styleable>
2.3 引入资源
private var mClearDrawable: Drawable? = null
init {
context.theme.obtainStyledAttributes(
attrs,
R.styleable.EditTextWithClear,
0,
0
).apply {
try {
val mClearDrawableId = getResourceId(R.styleable.EditTextWithClear_clearIcon, -1)
if (mClearDrawableId != -1) {
mClearDrawable = ContextCompat.getDrawable(context, mClearDrawableId)
}
} finally {
recycle()
}
}
}
2.4 当输入文本时显示,当失去焦点时消失
private fun toggleIconVisibility() {
val icon = if (mClearDrawable != null && isFocused) mClearDrawable else null
setCompoundDrawablesWithIntrinsicBounds(null, null, icon, null)
}
override fun onTextChanged(
text: CharSequence?,
start: Int,
lengthBefore: Int,
lengthAfter: Int
) {
super.onTextChanged(text, start, lengthBefore, lengthAfter)
toggleIconVisibility()
}
override fun onFocusChanged(focused: Boolean, direction: Int, previouslyFocusedRect: Rect?) {
super.onFocusChanged(focused, direction, previouslyFocusedRect)
toggleIconVisibility()
}
2.5 点击后松开实现清除
override fun onTouchEvent(event: MotionEvent?): Boolean {
// 这里假设清除按钮的中心在EditText高度的一半处,并且适当加大点击区域
event?.let { e ->
mClearDrawable?.let {
if (e.action == MotionEvent.ACTION_UP
&& e.x > width - it.intrinsicWidth - 10
&& e.x < width + 10
&& e.y > height / 2 - it.intrinsicHeight / 2 - 10
&& e.y < height / 2 + it.intrinsicHeight / 2 + 10
){
text?.clear()
}
}
}
performClick()
return super.onTouchEvent(event)
}
//有些设备只有触摸没有点击,所以这里重写一下点击事件
override fun performClick(): Boolean {
return super.performClick()
}
2.6 使用
app:clearIcon="@drawable/ic_baseline_clear_24"
在这里可以替换成想要的图标。