种草 Dribbble:从未见过如此 Q 弹的 Switcher,腾讯架构师深入讲解 Android 开发
attrs: AttributeSet ? = null,
defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
in
it {
attrs?.let { retrieveAttributes(attrs, defStyleAttr) }
}
privatefun retrieveAttributes(attrs: AttributeSet, defStyleAttr: Int) {
// retrieve cutom attributes
}
overridefun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
// setup switcher width and height
}
overridefun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
// setup helper sizes every time switcher size changed (radius, icon width...)
}
overridefun onDraw(canvas: Canvas ?) {
// just draw
}
}
[](
)接下来开始绘制
在默认(选中)状态下,我们的开关由 2 个圆角矩形(绿色和白色)组成
绘制它们非常简单,我们只需要计算白色矩形的位置并将偏移量iconTranslateX
传递给 Android KTX Canvas.withTranslation
扩展即可:
overridefun onDraw(canvas: Canvas ?) {
// draw switcher (green rect)
canvas?.drawRoundRect(switcherRect, switcherCornerRadius, switcherCornerRadius, switcherPaint)
// draw icon (white rect)
canvas?.withTranslation(x = iconTranslateX) {
drawRoundRect(iconRect, switcherCornerRadius, switcherCornerRadius, iconPaint)
}
}
[](
)开始分解动画
动画部分,我们使用ValueAnimator
来实现,使用它的ofFloat(float... values)
方法,我们需要三个动画:
1、
switcherAnimator
: 切换器图标动画,从白色矩形到圆形,反之亦然2、
translateAnimator
: 为切换器图标从左到右的过渡设置动画,反之亦然;3、
colorAnimator
: 将颜色从绿色(选中)更改为红色,反之亦然。
让我们先看一下switcherAnimator
动画,设置0
为动画的开始值,1
为动画的结束值。
// ...
var amplitude = BOUNCE_ANIM_AMPLITUDE_IN
var frequency = BOUNCE_ANIM_FREQUENCY_IN
var newProgress = 1f
if (!checked) {
amplitude = BOUNCE_ANIM_AMPLITUDE_OUT
frequency = BOUNCE_ANIM_FREQUENCY_OUT
newProgress = 0f
}
val switcherAnimator = ValueAnimator.ofFloat(iconProgress, newProgress).apply {
addUpdateListener {
iconProgress = it.animatedValue asFloat
}
interpolator = BounceInterpolator(amplitude, frequency)
duration = SWITCHER_ANIMATION_DURATION
}
// ...
我们可以使用?[Evgenii Neumerzhitckii](
) 写的BounceInterpolator
来实现反弹效果,这非常适合我们的动画场景,不了解的可以看一下这片文章:[evgenii.com/blog/spring…](
),它解释了BounceInterpolator
是如何工作的。
在 Android KTX addUpdateListener
扩展中,我们更新了progress
的值,然后触发invalidate
方法,最后重新绘制了视图。
评论