androidxmlkotlinandroid-seekbar

I want to create a seekbar in android(xml and kotlin).How?


I want to create a seekbar like the picture below in android(xml and kotlin).How? Also I need to do the kotlin portions in a custom adapter.

I tried using github libraries,but it seemed to be not working at all,or I am confused as to how to implement it in my project.

Please help or guide me to create a seekbar like in the picture.enter image description here

I have somthing like this from chatGPT,but I need to make it look like the picture above.HOw??

class SeekbarView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : View(context, attrs, defStyleAttr) {

private val waveColor = Color.BLUE
private val thumbColor = Color.RED

private val progressPath = Path()
private val thumbPath = Path()

private val progressPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
    style = Paint.Style.FILL
    color = waveColor
}

private val thumbPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
    style = Paint.Style.FILL
    color = thumbColor
}

private val thumbRect = RectF()

private var progress = 0f
private var maxProgress = 100f

init {
    // Set up any additional initialization here
}

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
    val desiredWidth = suggestedMinimumWidth + paddingLeft + paddingRight
    val desiredHeight = suggestedMinimumHeight + paddingTop + paddingBottom
    val measuredWidth = measureDimension(desiredWidth, widthMeasureSpec)
    val measuredHeight = measureDimension(desiredHeight, heightMeasureSpec)
    setMeasuredDimension(measuredWidth, measuredHeight)
}

private fun measureDimension(desiredSize: Int, measureSpec: Int): Int {
    val mode = MeasureSpec.getMode(measureSpec)
    val size = MeasureSpec.getSize(measureSpec)

    return when (mode) {
        MeasureSpec.EXACTLY -> size
        MeasureSpec.AT_MOST -> desiredSize.coerceAtMost(size)
        MeasureSpec.UNSPECIFIED -> desiredSize
        else -> desiredSize
    }
}

override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    val width = width.toFloat()
    val height = height.toFloat()

    // Draw waveform
    progressPath.reset()
    val waveHeight = height / 2 // Height of the waveform
    val waveStep = width / 100 // Width of each waveform segment
    val centerY = height / 2 // Vertical center position
    progressPath.moveTo(0f, centerY)
    for (i in 0..50) {
        val x = i * waveStep
        val y = centerY + Math.sin(x / width * 2 * Math.PI + progress / maxProgress * 2 * Math.PI) * waveHeight
        progressPath.lineTo(x, y.toFloat())
    }
    progressPath.lineTo(width, centerY)
    progressPath.close()
    canvas.drawPath(progressPath, progressPaint)


}

override fun onTouchEvent(event: MotionEvent): Boolean {
    val x = event.x
    when (event.action) {
        MotionEvent.ACTION_DOWN -> {
            return true
        }
        MotionEvent.ACTION_MOVE -> {
            val progress = x / width * maxProgress
            setProgress(progress.coerceIn(0f, maxProgress))
            invalidate()
            return true
        }
        MotionEvent.ACTION_UP -> {
            // Handle thumb release event here
            return true
        }
    }
    return super.onTouchEvent(event)
}

fun setProgress(progress: Float) {
    this.progress = progress
    invalidate()
}

fun setMaxProgress(maxProgress: Float) {
    this.maxProgress = maxProgress
    invalidate()
}

}


Solution

  • I used a github library https://github.com/massoudss/waveformSeekBar

    And in gradle(app)- Paste this

    implementation  'com.github.massoudss:waveformSeekBar:5.0.2'
    implementation 'com.github.lincollincol:amplituda:2.2.2'
    

    In gradle(project) - Paste this

    buildscript 
    {
    
    repositories {
    
      maven { url 'https://jitpack.io' }
    }
    dependencies {
    classpath 'com.google.gms:google-services:4.3.14'
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0"
    }
    }
    

    In xml file,use

               <ImageView
                    android:id="@+id/ivPause"
                    android:layout_width="35dp"
                    android:layout_height="35dp"
                    android:layout_marginStart="8dp"
                    android:layout_marginTop="35dp"
                    android:src="@drawable/ic_pause"
                    android:visibility="gone"
                    />
    
                <ImageView
                    android:id="@+id/ivPlay"
                    android:layout_width="35dp"
                    android:layout_height="35dp"
                    android:layout_marginStart="8dp"
                    android:layout_marginTop="35dp"
                    android:src="@drawable/ic_play"
                    android:visibility="visible"
                    />
    
    <com.masoudss.lib.WaveformSeekBar
     android:id="@+id/seekBar"
     android:layout_width="300dp"
     android:layout_height="100dp"
     android:layout_marginStart="20dp"
     android:layout_marginTop="2dp"
     android:layout_marginEnd="10dp"
     android:visibility="visible"
     app:wave_background_color="@color/light_green"
     app:wave_corner_radius="5dp"
     app:wave_gap="2dp"
     app:wave_gravity="center"
     app:wave_max_progress="100"
     app:wave_min_height="5dp"
     app:wave_padding_Bottom="2dp"
     app:wave_padding_left="2dp"
     app:wave_padding_right="2dp"
     app:wave_padding_top="2dp"
     app:wave_progress="50"
     app:wave_progress_color="@color/lead_list_followup"
     app:wave_visible_progress="50"
     app:wave_width="3dp" />
    

    Now if you want to use this seekbar to play audio file,Use the code below:

     binding.seekBar.setSampleFrom(File("/storage/self/primary/Music/Voice Recorder/darari ringtone.mp3"))
                    var mp: MediaPlayer? = null
                    val handler = Handler()
                    binding.ivPlay.setOnClickListener {
                        if (mp == null) {
                            mp = MediaPlayer.create(
                                context,
                                Uri.parse("/storage/self/primary/Music/Voice Recorder/darari ringtone.mp3")
                            )
                        }
                        mp?.start()
                        binding.seekBar.maxProgress = mp!!.duration.toFloat()
    
                        handler.postDelayed(object : Runnable {
                            override fun run() {
                                try {
                                    binding.seekBar.progress = mp!!.currentPosition.toFloat()
                                    handler.postDelayed(this, 600)
                                    if (!mp!!.isPlaying) {
                                        handler.removeCallbacksAndMessages(null)
                                        binding.ivPause.hide()
                                        binding.ivPlay.show()
                                    }
                                } catch (e: Exception) {
                                    binding.seekBar.progress = 0F
                                }
                            }
    
                        }, 0)
    
                        binding.ivPause.show()
                        binding.ivPlay.hide()
                    }
    
    
                    binding.ivPause.setOnClickListener {
                        if (mp?.isPlaying == true) {
                            mp?.pause()
                        }
                        binding.ivPlay.visibility = View.VISIBLE
                        binding.ivPause.visibility = View.GONE
                    }
    
    
    
                    binding.seekBar.apply {
                        onProgressChanged = object : SeekBarOnProgressChanged {
                            override fun onProgressChanged(
                                waveformSeekBar: WaveformSeekBar,
                                progress: Float,
                                fromUser: Boolean
                            ) {
                                if (fromUser) {
                                    mp?.seekTo(progress.toInt())
                                }
                            }
                        }
                    }