androidkotlinsliderseekbarandroid-slider

How to add color line on the seekbar slider properly?


I'm trying to make specific color line on the seekbar slider, like trying to tell the user that there's specific event on that timestamp of the video.

I want that extra color line is top of the slider line, and the line is bottom of the scrubber.

My expectation is like this:

Pic

The result i got:

Pic 2

My code is like this:

Player:

val seekBar = findViewById<EventOverlayBar>(R.id.seek_bar)

val eventSections = listOf(
            Pair(10, 20),  // Event 1 from 10s to 20s
            Pair(40, 50)   // Event 2 from 40s to 50s
)
val duration = 100  // The video is 100 seconds duration for the example

seekBar.setEventSections(eventSections, duration)

Constructor:


class EventOverlayBar @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : androidx.appcompat.widget.AppCompatSeekBar(context, attrs) {

    private val eventPaint = Paint().apply {
        color = Color.BLUE
        style = Paint.Style.FILL
    }

    private var eventSections: List<Pair<Int, Int>> = listOf()
    private var duration: Int = 0

    fun setEventSections(adSections: List<Pair<Int, Int>>, duration: Int) {
        this.eventSections = adSections
        this.duration = duration
        invalidate()
    }

    override fun dispatchDraw(canvas: Canvas) {
        super.dispatchDraw(canvas)
        drawEventSections(canvas)
    }

    private fun drawEventSections(canvas: Canvas) {
        if (duration == 0) return

        val barWidth = width - paddingLeft - paddingRight
        val barHeight = height / 2

        for ((start, end) in eventSections) {
            val startX = paddingLeft + (start.toFloat() / duration) * barWidth
            val endX = paddingLeft + (end.toFloat() / duration) * barWidth
            canvas.drawRect(startX, barHeight.toFloat(), endX, (barHeight + 10).toFloat(), eventPaint)
        }
    }
}

Seekbar:

<com.example.EventOverlayBar
                        android:id="@+id/exo_progress"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
/>

Solution

  • I think i found a way to do this, it doesn't meet my earlier expectation but I'll take it instead.

    There's a thing named ad marker on DefaultTimeBar, but it can't use custom width for each multiple groups. So instead of hard coded the width, I'm using start and end of the event instead.

    Here is my latest code:

    <androidx.media3.ui.DefaultTimeBar
                            android:id="@+id/exo_progress"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
    />
    

    Player:

    val adGroupTimesMs = longArrayOf(1000, 5000)
    val adGroupPlayed = adGroupTimesMs.map { false }.toBooleanArray()
    seekBar.apply {
        setAdMarkerColor(resources.getColor(android.R.color.holo_red_dark))
        setPlayedAdMarkerColor(resources.getColor(android.R.color.holo_red_dark))
        setAdGroupTimesMs(adGroupTimesMs, adGroupPlayed, adGroupTimesMs.size)
    }
    

    And the result is like this: enter image description here