• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar

陈文管的博客

分享有价值的内容

  • Android
  • Affiliate
  • SEO
  • 前后端
  • 网站建设
  • 自动化
  • 开发资源
  • 关于

Android 残影数字动画实现详解

2023年2月20日发布 | 最近更新于 2023年8月24日

Android 残影数字属性动画效果,以及叠加梯形基座自定义View实现详解,附上GitHub代码资源(Kotlin)。

项目上要实现一个残影叠加效果的评分动画效果,常规数字显示较轻的残影动效,逢10的倍数残影效果加重,并在结束的时候带有抖动效果,分数底座跟随评分等级切换颜色,先看下实现效果GIF。

初始版本实现(ScoreAnimView):

Android 重影数字动画效果实现

优化后的版本实现(GhostingTextView):

数字残影自定义控件

一、实现原理详解(初始版本)

首先是得分动画,叠加了缩放、alpha透明度渐变、从下往上Y轴方向的偏移,以及加重动效时候阴影在X轴方向的偏移和描边stroke粗细大小的变化。

1)从底部冒出动画效果

略过缩放和alpha透明度渐变常规操作,如果只是配置缩放和透明度渐变则字体是从布局中心点开始做缩放,不符合设计要求的效果,需要叠加从下往上Y轴方向的偏移,比如translationY属性从100->0就是从下往上冒出来的效果。在不同的屏幕尺寸下,不同大小的文本SCORE_TRANSLATION_Y和X_TRANSLATION_Y偏移量参数要各自适配,这样X和数字文本从下往上缩放显示的时候底部可以在同一水平线上。

val transYAnimator: ObjectAnimator =
    ObjectAnimator.ofFloat(scoreNum, "translationY", SCORE_TRANSLATION_Y, 0f)

2)残影叠加动画效果

残影效果则是在布局里面使用两个相同的控件叠加,一前一后,前面控件的做常规的动画,后面控件的延迟50ms执行动画,这样层叠错开显示形成残影效果。逢10的时候做描边stroke粗细大小的渐变,以及阴影在X轴方向偏移量的渐变,达到加重突出的动画效果。

前后两个控件分别用独立的属性动画执行,使用AnimatorSet的playTogether同步触发控件动画的执行。

//上层字体动画
mPackAnimSet = AnimatorSet()
mPackAnimSet?.playTogether(mScoreAnimSet, mScorePlusAnimSet)
//底层残影叠加动画
mPackAnimSetShadow = AnimatorSet()
mPackAnimSetShadow?.playTogether(mScoreAnimShadowSet, mScorePlusShadowAnimSet)
//底层残影叠加加重动画
mPackAnimSpecSetShadow = AnimatorSet()
mPackAnimSpecSetShadow?.playTogether(mScoreAnimShadowSpecSet, mScorePlusShadowAnimSet)

而阴影在X轴的偏移量没有直接的属性函数可以调用,需要间接通过setShadowLayer函数来配置实现:

fun setShadowDx(dx: Float){
    super.setShadowLayer(shadowRadius, dx, shadowDy, shadowColor)
}

镂空的数字文本则通过加载字体库,并自定义画笔的style和strokeWidth参数实现,这样可以自己配置strokeWidth属性的渐变。

//加载字体库
val fontScore = Typeface.createFromAsset(context.getAssets(), "Montserrat-ExtraBoldItalic.ttf")
setTypeface(fontScore)
//绘制镂空字体
override fun onDraw(canvas: Canvas?) {
    paint.style = Paint.Style.STROKE
    paint.color = mStrokeColor
    paint.strokeWidth = mStrokeWidth
    super.onDraw(canvas)
}

3)梯形底座

实际是构造三个三角形Path区域,通过LinearGradient配置渐变到三角形三分二高度为透明,实现绘制叠加梯形的的底座效果。具体实现见代码。

二、实现原理详解(优化版本)

首先是使用属性动画从0.3到1.0的参数缩放,在缩放的过程中改变文本尺寸大小:

var scaleAnimator = ObjectAnimator.ofFloat(this, "scaleShift", 0.3f, 1.0f)
fun setScaleShift(ratio: Float) {
    mIsAnimEnd = false
    mScaleRatio = ratio
    mAnimTextSize = TEXT_SIZE * ratio
    invalidate()
}

使用for循环逐个减小文本大小尺寸,配合逐级递减的Alpha透明度绘制残影效果:

for (i in GHOSTING_NUMBER downTo 0) {
    var itemAlpha = 255 - 255 / GHOSTING_NUMBER * i
    if (itemAlpha < 0) {
        itemAlpha = 0
    }
    drawGhosting(mAnimTextSize - i * 20, itemAlpha, canvas)
}

而加重的残影效果通过strokeWidth的属性渐变来实现:

val strokeAnimator: ObjectAnimator =
    ObjectAnimator.ofFloat(
        this,
        "strokeWidth",
        VIEW_STROKE_WIDTH,
        VIEW_STROKE_WIDTH * 5,
        VIEW_STROKE_WIDTH
    )
fun setStrokeWidth(strokeWidth: Float) {
    mStrokeWidth = strokeWidth
}

逢10倍数数字抖动的动效通过translationX和translationY的变化来实现:

val translateXAnim: ObjectAnimator =
    ObjectAnimator.ofFloat(this, "translationX", 8f, 0f, 8f, 0f,8f, 0f,8f, 0f,8f, 0f, 8f, 0f, 8f, 0f,8f, 0f,8f, 0f,8f, 0f)
val translateYAnim: ObjectAnimator =
    ObjectAnimator.ofFloat(this, "translationY", 4f, 0f, 4f, 0f, 4f, 0f,4f, 0f,4f, 0f, 4f, 0f, 4f, 0f, 4f, 0f,4f, 0f,4f, 0f)

这边需要注意的点:在布局中使用GhostingTextView需要配置minWidth和minHeight属性,因为重写了onDraw,也没写死布局尺寸,不配置会出现绘制显示的时候显示不全的问题。

另外,目前使用的字体在显示数字7的时候,右上角被裁切,显示不全,这个通过添加空格解决,为了不让空格占的位置过大,通过SpannableString设置较小的字体。

if (mScore % 10 == 7) {
    //避免右上角被裁剪,使用小尺寸空格填充
    var str7 = " ${mScore} "
    var spannable7 = SpannableString(str7)
    spannable7.setSpan(mScoreTailAbsoluteSizeSpan, 0, 1, Spannable.SPAN_INCLUSIVE_INCLUSIVE)
    spannable7.setSpan(mScoreAbsoluteSizeSpan, 1, str7.length - 1, Spannable.SPAN_INCLUSIVE_INCLUSIVE)
    spannable7.setSpan(mScoreTailAbsoluteSizeSpan, str7.length - 1, str7.length, Spannable.SPAN_INCLUSIVE_INCLUSIVE)
    mGhostingTv.setScore(spannable7)
}

三、GitHub仓库链接地址

https://github.com/wenguan0927/GhostingAnimView

扩展阅读:

美图手机音乐Widget动画实现

Android 心率动画自定义控件实现

Android 卡片旋转切换动效实现详解

转载请注明出处:陈文管的博客 – Android 残影数字动画实现详解

扫码或搜索:文呓

博客公众号

微信公众号 扫一扫关注

文章目录

  • 一、实现原理详解(初始版本)
    • 1)从底部冒出动画效果
    • 2)残影叠加动画效果
    • 3)梯形底座
  • 二、实现原理详解(优化版本)
  • 三、GitHub仓库链接地址
博客公众号

闽ICP备18001825号-1 · Copyright © 2025 · Powered by chenwenguan.com