实现了Android录音,语音输入时的竖线波纹动画效果和音乐播放时的跳动效果

效果

实现原理

实现了两种运动效果:

1.从左到右移动

假设柱状图的高度是一个对列

27,17,38,91,38,24,8,60,38,14,8

8,27,17,38,91,38,24,8,60,38,14

14,8,27,17,38,91,38,24,8,60,38

从左到右移动实际上就是不断的将队列中的最后一个插入到队列的第一个。

代码:

runnable = object : Runnable {
    override fun run() {
        val last = bodyWaveList.pollLast()
        bodyWaveList.addFirst(last)
        invalidate()
        valHandler.postDelayed(this, duration);//循环调用重绘
    }
}
valHandler.post(runnable)

2.上下跳动

假设柱状图是一个队列

27,17,38,91,38,24,8,60,38,14,8

上下跳动就是将队列的高度,从0%-100%变化

代码:

valueAnimator.addUpdateListener {
        valueAnimatorOffset = it.getAnimatedValue() as Float
        invalidate()
}
valueAnimator.start()

然后在onDraw绘制时高度*valueAnimatorOffset

绘制

代码:

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)

        waveList.clear()
        waveList.addAll(headerWaveList)
        waveList.addAll(bodyWaveList)
        waveList.addAll(footerWaveList)

        paintLine?.strokeWidth = lineWidth
        paintLine?.color = lineColor

        for (i in waveList.indices) {
            var startX = 0f
            var startY = 0f
            var endX = 0f
            var endY = 0f

            var offset = 1f
            if (i >= headerWaveList.size && i < (waveList.size - footerWaveList.size)) {//模式1 ,排除掉头尾
                offset = valueAnimatorOffset
            }

            val lineHeight = waveList[i] / 100.0 * measuredHeight * offset

            val absoluteGravity = Gravity.getAbsoluteGravity(showGravity, layoutDirection);

            when (absoluteGravity and Gravity.HORIZONTAL_GRAVITY_MASK) {//左中右的位置
                Gravity.CENTER_HORIZONTAL -> {
                    val lineSize = waveList.size
                    val allLineWidth = lineSize * (lineSpace + lineWidth)
                    if (allLineWidth < measuredWidth) {
                        startX = (i * (lineSpace + lineWidth) + lineWidth / 2) + ((measuredWidth - allLineWidth) / 2)
                    } else {
                        startX = i * (lineSpace + lineWidth) + lineWidth / 2
                    }
                    endX = startX
                }

                Gravity.RIGHT -> {
                    val lineSize = waveList.size
                    val allLineWidth = lineSize * (lineSpace + lineWidth)
                    if (allLineWidth < measuredWidth) {
                        startX = (i * (lineSpace + lineWidth) + lineWidth / 2) + (measuredWidth - allLineWidth)
                    } else {
                        startX = i * (lineSpace + lineWidth) + lineWidth / 2
                    }
                    endX = startX
                }

                Gravity.LEFT -> {
                    startX = i * (lineSpace + lineWidth) + lineWidth / 2
                    endX = startX
                }
            }


            when (showGravity and Gravity.VERTICAL_GRAVITY_MASK) {//上中下的位置
                Gravity.TOP -> {
                    startY = 0f
                    endY = lineHeight.toFloat()
                }

                Gravity.CENTER_VERTICAL -> {
                    startY = (measuredHeight / 2 - lineHeight / 2).toFloat()
                    endY = (measuredHeight / 2 + lineHeight / 2).toFloat()
                }

                Gravity.BOTTOM -> {
                    startY = (measuredHeight - lineHeight).toFloat()
                    endY = measuredHeight.toFloat()
                }

            }

            canvas?.drawLine(
                startX,
                startY,
                endX,
                endY,
                paintLine
            )

        }
    }

地址

https://github.com/xfans/VoiceWaveView

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注