一、前言
本篇我们来学习拓展已有的 View,比如继承 EditText 来对它进行拓展。要实现的效果如下:
二、MaterialEditText
分析一下,首先第一步,预留浮动文字的距离。可以在初始化时通过 setPadding 来设置。
第二步,绘制浮动文字,文字可以通过设置的 hint 值获取。
第三步,通过动画来实现浮动文字的透明度、垂直偏移的变化。
完整代码如下:
class MateriaEditText(context: Context, attributeSet: AttributeSet) : AppCompatEditText(context, attributeSet) {
//字体大小
val TEXT_SIZE = Utils.dp2px(12)
//离输入框的距离
val TEXT_MARGIN = Utils.dp2px(8)
//垂直偏移
val TEXT_VERTICAL_OFFSET = Utils.dp2px(20)
//水平偏移
val TEXT_HORIZENTAL_OFFSET = Utils.dp2px(4)
//动画偏移
val TEXT_ANIMATION_OFFSET = Utils.dp2px(16)
//浮动文字是否显示
var floatingTextShown = false
//背景偏移
var backgroundPadding = Rect()
var mPaint = Paint(Paint.ANTI_ALIAS_FLAG)
lateinit var objectAnimator: ObjectAnimator
//动画进度
var progress: Float = 0f
set(value) {
field = value
invalidate()
}
init {
mPaint.textSize = Utils.dp2px(12)
background.getPadding(backgroundPadding)
setPadding(paddingLeft, (backgroundPadding.top + TEXT_SIZE + TEXT_MARGIN).toInt(), paddingRight, paddingBottom)
addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
if (floatingTextShown && TextUtils.isEmpty(s)) {
floatingTextShown = false
getAnimator().reverse()
} else if (!floatingTextShown && !TextUtils.isEmpty(s)) {
floatingTextShown = true
getAnimator().start()
}
}
})
}
fun getAnimator(): ObjectAnimator {
if (!this::objectAnimator.isInitialized) {
objectAnimator = ObjectAnimator.ofFloat(this, "progress", 0f, 1f)
}
return objectAnimator
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
mPaint.alpha = (0xff * progress).toInt()
canvas.drawText(
hint.toString(), TEXT_HORIZENTAL_OFFSET,
TEXT_VERTICAL_OFFSET + TEXT_ANIMATION_OFFSET * (1 - progress), mPaint
)
}
}
过程不复杂,大家可以动手实现一下。实现效果如下: