开发者

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

开发者 https://www.devze.com 2022-12-25 10:17 出处:网络 作者: timer
目录即刻点赞展示自己如何实现这种数字切换呢?效果展示源码总结即刻点赞展示
目录
  • 即刻点赞展示
  • 自己如何实现这种数字切换呢?
    • 效果展示
    • 源码
  • 总结

    即刻点赞展示

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

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

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

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

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

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

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

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

    效果展示

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

    源码

    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 = 200fandroid
        }
    
        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)
      js      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, -off开发者_C学习setPercent)
                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) {
           www.devze.com     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模仿即刻点编程赞数字切换内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    关注公众号