看到这个效果,可能会想到完全自定义一个控件,其实我们在系统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 = trueprivate var tryPlayableStartPos = 10private var tryPlayableEndPos = 60private 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 = truestyle = Paint.Style.FILL_AND_STROKEcolor = context.getColor(R.color.player_try_playable_progress_color)}}private val tryPlayableProgressPaint by lazy {Paint().apply {isAntiAlias = truestyle = Paint.Style.FILL_AND_STROKEcolor = context.getColor(R.color.player_track_color)}}private var playSeekBarChangeListener: OnPlaySeekBarChangeListener? = nullinit {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) * percentval bottom = (height - paddingBottom).toFloat()canvas?.drawRect(left, top, right, bottom, paint)}fun setTryPlayable(tryPlayable: Boolean) {this.tryPlayable = tryPlayableprogressDrawable = if (tryPlayable) {fakeProgressDrawable} else {normalProgressDrawable}invalidate()}fun setTryPlayProgress(tryPlayableStartPos: Int, tryPlayableEndPos: Int) {this.tryPlayableStartPos = tryPlayableStartPosthis.tryPlayableEndPos = tryPlayableEndPosinvalidate()}fun setOnPlaySeekBarChangeListener(listener: OnPlaySeekBarChangeListener) {this.playSeekBarChangeListener = listener}interface OnPlaySeekBarChangeListener : OnSeekBarChangeListener {// 超出试听区域fun onOverTryPlayableArea()}
}