Android自定义View模仿即刻点赞数字切换效果实例

 更新时间:2022年12月24日 11:23:49   作者:timer  
有一个项目是仿即刻的点赞,这篇文章主要给大家介绍了关于Android自定义View模仿即刻点赞数字切换效果的相关资料,文中通过示例代码介绍 的非常详细,需要的朋友可以参考下

即刻点赞展示

点赞的数字增加和减少并不是整个替换,而是差异化替换。再加上动画效果就看的很舒服。

自己如何实现这种数字切换呢?

下面用一张图来展示我的思路:

现在只需要根据这张图,写出对应的动画即可。 分为2种场景:

  • 数字+1:
    • 差异化的数字从3号区域由渐变动画(透明度 0- 255) + 偏移动画 (3号区域绘制文字的基线,2号区域绘制文字的基线),将数字移动到2号位置处
    • 差异化的数字从2号区域由渐变动画(透明度 255- 0) + 偏移动画(2号区域绘制文字的基线,1号区域绘制文字的基线),将数字移动到1号位置处
  • 数字-1
    • 差异化的数字从1号区域由渐变动画(透明度 0- 255) + 偏移动画 (1号区域绘制文字的基线,2号区域绘制文字的基线),将数字移动到2号位置处
    • 差异化的数字从2号区域由渐变动画(透明度 255- 0) + 偏移动画(2号区域绘制文字的基线,3号区域绘制文字的基线),将数字移动到3号位置处

公共部分就是: 不变的文字不需要做任何处理,绘制在2号区域就行。绘制差异化文字时,需要加上不变的文字的宽度就行。

效果展示

源码

class LikeView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    private val paint = Paint().also {
        it.isAntiAlias = true
        it.textSize = 200f
    }

    private val textRect0 = Rect(300, 100, 800, 300)
    private val textRect1 = Rect(300, 300, 800, 500)
    private val textRect2 = Rect(300, 500, 800, 700)

    private var nextNumberAlpha: Int = 0
        set(value) {
            field = value
            invalidate()
        }

    private var currentNumberAlpha: Int = 255
        set(value) {
            field = value
            invalidate()
        }

    private var offsetPercent = 0f
        set(value) {
            field = value
            invalidate()
        }

    private val fontMetrics: FontMetrics = paint.fontMetrics
    private var currentNumber = 99
    private var nextNumber = 0
    private var motionLess = currentNumber.toString()
    private var currentMotion = ""
    private var nextMotion = ""

    private val animator: ObjectAnimator by lazy {
        val nextNumberAlphaAnimator = PropertyValuesHolder.ofInt("nextNumberAlpha", 0, 255)
        val offsetPercentAnimator = PropertyValuesHolder.ofFloat("offsetPercent", 0f, 1f)
        val currentNumberAlphaAnimator = PropertyValuesHolder.ofInt("currentNumberAlpha", 255, 0)
        val animator = ObjectAnimator.ofPropertyValuesHolder(
            this,
            nextNumberAlphaAnimator,
            offsetPercentAnimator,
            currentNumberAlphaAnimator
        )
        animator.duration = 200
        animator.interpolator = DecelerateInterpolator()
        animator.addListener(
            onEnd = {
                currentNumber = nextNumber
            }
        )
        animator
    }

    override fun onDraw(canvas: Canvas) {
        paint.alpha = 255

        paint.color = Color.LTGRAY
        canvas.drawRect(textRect0, paint)

        paint.color = Color.RED
        canvas.drawRect(textRect1, paint)

        paint.color = Color.GREEN
        canvas.drawRect(textRect2, paint)

        paint.color = Color.BLACK
        if (motionLess.isNotEmpty()) {
            drawText(canvas, motionLess, textRect1, 0f)
        }

        if (nextMotion.isEmpty() || currentMotion.isEmpty()) {
            return
        }

        val textHorizontalOffset =
            if (motionLess.isNotEmpty()) paint.measureText(motionLess) else 0f
        if (nextNumber > currentNumber) {
            paint.alpha = currentNumberAlpha
            drawText(canvas, currentMotion, textRect1, textHorizontalOffset, -offsetPercent)
            paint.alpha = nextNumberAlpha
            drawText(canvas, nextMotion, textRect2, textHorizontalOffset, -offsetPercent)
        } else {
            paint.alpha = nextNumberAlpha
            drawText(canvas, nextMotion, textRect0, textHorizontalOffset, offsetPercent)
            paint.alpha = currentNumberAlpha
            drawText(canvas, currentMotion, textRect1, textHorizontalOffset, offsetPercent)
        }
    }

    private fun drawText(
        canvas: Canvas,
        text: String,
        rect: Rect,
        textHorizontalOffset: Float = 0f,
        offsetPercent: Float = 0f
    ) {
        canvas.drawText(
            text,
            rect.left.toFloat() + textHorizontalOffset,
            rect.top + (rect.bottom - rect.top) / 2f - (fontMetrics.bottom + fontMetrics.top) / 2f + offsetPercent * 200,
            paint
        )
    }


    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        animator.end()
    }

    fun plus() {
        if (currentNumber == Int.MAX_VALUE) {
            return
        }
        nextNumber = currentNumber + 1

        processText(findEqualsStringIndex())

        if (animator.isRunning) {
            return
        }
        animator.start()
    }

    fun minus() {
        if (currentNumber == 0) {
            return
        }
        nextNumber = currentNumber - 1
        processText(findEqualsStringIndex())
        if (animator.isRunning) {
            return
        }
        animator.start()
    }

    private fun findEqualsStringIndex(): Int {
        var equalIndex = -1
        val nextNumberStr = nextNumber.toString()
        val currentNumberStr = currentNumber.toString()

        val endIndex = min(currentNumberStr.length, nextNumberStr.length) - 1

        for (index in 0..endIndex) {
            if (nextNumberStr[index] != currentNumberStr[index]) {
                break
            }
            equalIndex = index
        }
        return equalIndex
    }

    private fun processText(index: Int) {
        val currentNumberStr = currentNumber.toString()
        val nextNumberStr = nextNumber.toString()
        if (index == -1) {
            motionLess = ""
            currentMotion = currentNumberStr
            nextMotion = nextNumberStr
        } else {
            motionLess = currentNumberStr.substring(0, index + 1)
            currentMotion = currentNumberStr.substring(index + 1)
            nextMotion = nextNumberStr.substring(index + 1)
        }
    }
}

总结

到此这篇关于Android自定义View模仿即刻点赞数字切换效果的文章就介绍到这了,更多相关Android模仿即刻点赞数字切换内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Android 页面多状态布局管理的开发

    Android 页面多状态布局管理的开发

    页面多状态布局是开发中常见的需求,即页面在不同状态需要显示不同的布局,这篇文章主要介绍了Android 页面多状态布局管理的开发,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-10-10
  • 利用Jetpack Compose实现主题切换功能

    利用Jetpack Compose实现主题切换功能

    这篇文章主要介绍了如何利用Android中的Jetpack Compose实现主题切换功能,文中的示例代码讲解详细,对我们学习有一定帮助,需要的可以参考一下
    2022-01-01
  • 详解Android的反编译和代码混淆

    详解Android的反编译和代码混淆

    本篇文章主要介绍了详解Android的反编译和代码混淆,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-11-11
  • Android实现手机壁纸改变的方法

    Android实现手机壁纸改变的方法

    这篇文章主要介绍了Android实现手机壁纸改变的方法,以完整实例形式分析了Android手机壁纸改变的方法,包括页面布局及属性设置的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-09-09
  • Android标题栏上添加多个Menu按钮的实例

    Android标题栏上添加多个Menu按钮的实例

    这篇文章主要介绍了Android标题栏上添加多个Menu按钮的实例的相关资料,这里提供简单实例说明如何添加多个menu按钮的方法,需要的朋友可以参考下
    2017-09-09
  • Android Handler的详细介绍

    Android Handler的详细介绍

    Handler当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件,进行事件分发
    2013-09-09
  • python只需30行代码就能记录键盘的一举一动

    python只需30行代码就能记录键盘的一举一动

    这篇文章主要介绍了如何用python只写30行代码就能记录键盘的一举一动,感兴趣的同学快来看看吧,新手小白也能掌握
    2021-08-08
  • Android中CheckBox复选框控件使用方法详解

    Android中CheckBox复选框控件使用方法详解

    这篇文章主要为大家详细介绍了Android中CheckBox复选框控件的使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • Android实现显示系统实时时间

    Android实现显示系统实时时间

    这篇文章主要为大家详细介绍了Android实现显示系统实时时间,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-05-05
  • Android启动屏实现左右滑动切换查看功能

    Android启动屏实现左右滑动切换查看功能

    这篇文章主要介绍了Android启动屏实现左右滑动切换查看功能的相关资料,针对新功能属性介绍和启动屏进行详细讲解,感兴趣的小伙伴们可以参考一下
    2016-01-01

最新评论