自定义歌曲试听SeekBar

在这里插入图片描述
看到这个效果,可能会想到完全自定义一个控件,其实我们在系统Seekbar的基础上,将progressDrawable中progress背景设为透明后,叠加绘制试听状态下的进度区域即可

class PlayerSeekBar @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0,
    defStyleRes: Int = 0,
) : SeekBar(context, attrs, defStyleAttr, defStyleRes) {

    private var tryPlayable = true
    private var tryPlayableStartPos = 10
    private var tryPlayableEndPos = 60
    private val normalProgressDrawable: Drawable? =
        context.getDrawable(R.drawable.bg_player_seekbar)
    private val fakeProgressDrawable: Drawable? =
        context.getDrawable(R.drawable.bg_player_seekbar_fake)

    private val tryPlayableBgPaint: Paint by lazy {
        Paint().apply {
            isAntiAlias = true
            style = Paint.Style.FILL_AND_STROKE
            color = context.getColor(R.color.player_try_playable_progress_color)
        }
    }

    private val tryPlayableProgressPaint by lazy {
        Paint().apply {
            isAntiAlias = true
            style = Paint.Style.FILL_AND_STROKE
            color = context.getColor(R.color.player_track_color)
        }
    }

    private var playSeekBarChangeListener: OnPlaySeekBarChangeListener? = null

    init {
        setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
            override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
                playSeekBarChangeListener?.onProgressChanged(seekBar, progress, fromUser)
            }

            override fun onStartTrackingTouch(seekBar: SeekBar?) {
                playSeekBarChangeListener?.onStartTrackingTouch(seekBar)
            }

            override fun onStopTrackingTouch(seekBar: SeekBar?) {
                playSeekBarChangeListener?.onStopTrackingTouch(seekBar)
                if (isOverTryPlayableAre()) {
                    playSeekBarChangeListener?.onOverTryPlayableArea()
                }
            }
        })
    }

    private fun isOverTryPlayableAre(): Boolean {
        return tryPlayable && (progress > tryPlayableEndPos || progress < tryPlayableStartPos)
    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        if (tryPlayable) {
            val tryPlayableProgress =
                progress.coerceAtLeast(tryPlayableStartPos).coerceAtMost(tryPlayableEndPos)
            // 试听区域背景
            drawTryPlayableRect(canvas, tryPlayableBgPaint, tryPlayableStartPos, tryPlayableEndPos)
            // 试听区域进度
            drawTryPlayableRect(
                canvas,
                tryPlayableProgressPaint,
                tryPlayableStartPos,
                tryPlayableProgress
            )
        }

    }

    private fun drawTryPlayableRect(canvas: Canvas?, paint: Paint, startPos: Int, endPos: Int) {
        val percent = (endPos - startPos) * 1.0F / (max - min)
        val left =
            paddingLeft + (startPos - min) * 1.0F / (max - min) * (width - paddingLeft - paddingRight)
        val top = paddingTop.toFloat()
        val right = left + (width - paddingLeft - paddingRight) * percent
        val bottom = (height - paddingBottom).toFloat()
        canvas?.drawRect(left, top, right, bottom, paint)
    }

    fun setTryPlayable(tryPlayable: Boolean) {
        this.tryPlayable = tryPlayable
        progressDrawable = if (tryPlayable) {
            fakeProgressDrawable
        } else {
            normalProgressDrawable
        }
        invalidate()
    }

    fun setTryPlayProgress(tryPlayableStartPos: Int, tryPlayableEndPos: Int) {
        this.tryPlayableStartPos = tryPlayableStartPos
        this.tryPlayableEndPos = tryPlayableEndPos
        invalidate()
    }

    fun setOnPlaySeekBarChangeListener(listener: OnPlaySeekBarChangeListener) {
        this.playSeekBarChangeListener = listener
    }

    interface OnPlaySeekBarChangeListener : OnSeekBarChangeListener {
        // 超出试听区域
        fun onOverTryPlayableArea()
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值