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() // 保存每个柱子动画的列表 private val animators = mutableListOf() 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) } }