Musicoo/app/src/main/java/relax/offline/music/view/MusicBarsView.kt
2024-05-24 20:36:01 +08:00

85 lines
2.7 KiB
Kotlin

package relax.offline.music.view
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.util.AttributeSet
import android.util.TypedValue
import android.view.View
class MusicBarsView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
// 用于绘制柱子的 Paint 对象
private val barPaint = Paint().apply {
color = Color.parseColor("#FF80F988")
style = Paint.Style.FILL
}
// 每个柱子的宽度
private val barWidth = dpToPx(context,4f)
// 柱子之间的间距
private val barSpacing = dpToPx(context,2f)
// 柱子的圆角半径
private val cornerRadius = dpToPx(context,16f)
// 保存每个柱子高度的列表
private val barHeights = mutableListOf<Float>()
// 保存每个柱子动画的列表
private val animators = mutableListOf<ValueAnimator>()
init {
// 初始化柱子的高度并启动动画
for (i in 0 until 3) {
barHeights.add(0f)
startAnimation(i)
}
}
// 启动动画
private fun startAnimation(index: Int) {
val animator = ValueAnimator.ofFloat(0f, 1f).apply {
duration = 500 // 动画持续时间为 500 毫秒
repeatCount = ValueAnimator.INFINITE // 无限重复动画
repeatMode = ValueAnimator.REVERSE // 反向重复
addUpdateListener { animation ->
// 更新柱子的高度
barHeights[index] = (animation.animatedValue as Float) * height
invalidate() // 重绘 View
}
startDelay = index * 200L // 设置动画的开始延迟时间
}
animators.add(animator)
animator.start() // 启动动画
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val barCount = barHeights.size
val totalWidth = barCount * barWidth + (barCount - 1) * barSpacing
val startX = (width - totalWidth) / 2
// 绘制每个柱子
barHeights.forEachIndexed { index, barHeight ->
val left = startX + index * (barWidth + barSpacing)
val top = height - barHeight
val right = left + barWidth
val bottom = height.toFloat()
canvas.drawRoundRect(left, top, right, bottom, cornerRadius, cornerRadius, barPaint)
}
}
fun dpToPx(context: Context, dp: Float): Float {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.resources.displayMetrics)
}
}