一、前言
本篇我們來學習拓展已有的 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
)
}
}
過程不復雜,大家可以動手實現一下。實現效果如下: