Android SeekBar Kotlin Example
Android SeekBar is a user-controlled progress widget. It looks similar to a progress bar, but it adds a draggable thumb so the user can choose a numeric value by moving the thumb left or right.
In this Kotlin Android SeekBar tutorial, you will learn how to add a SeekBar in an XML layout, listen for progress changes, get the selected value, detect when the user starts and stops dragging, and use a modern AndroidX View Binding version for new projects.
A SeekBar is commonly used for volume, brightness, media playback position, font size, timer duration, percentage selection, and similar settings where the user can choose a value within a range.
The following GIF shows how a user can touch the trackbar, and seek it to the left or right of the bar.

Android SeekBar progress value and listener callbacks in Kotlin
A SeekBar stores its selected position as an integer progress value. By default, the progress range is from 0 to 100. You can change the upper limit with android:max in XML or with max in Kotlin. The selected value can be read from seekBar.progress.
| SeekBar part | Purpose in Kotlin Android |
|---|---|
android:max | Sets the maximum progress value for the SeekBar. |
android:progress | Sets the initial selected progress value. |
setOnSeekBarChangeListener() | Registers callbacks for progress changes and drag events. |
onProgressChanged() | Runs when the progress value changes. |
fromUser | Tells whether the progress change came from the user or from code. |
Kotlin Android SeekBar XML and OnSeekBarChangeListener code
Following is a quick code snippet to use SeekBar in your layout file and Kotlin file respectively.
<SeekBar
android:id="@+id/seekbar"
android:layout_width="match_parent"
android:padding="15dp"
android:layout_height="wrap_content" />
import android.os.Bundle
import android.widget.SeekBar
import android.widget.SeekBar.OnSeekBarChangeListener
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : /** Other Classes, */OnSeekBarChangeListener {
override fun onCreate(savedInstanceState: Bundle?) {
this.seekbar!!.setOnSeekBarChangeListener(this)
}
override fun onProgressChanged(seekBar: SeekBar, progress: Int,
fromUser: Boolean) {
// called when progress is changed
}
override fun onStartTrackingTouch(seekBar: SeekBar) {
// called when tracking the seekbar is started
}
override fun onStopTrackingTouch(seekBar: SeekBar) {
// called when tracking the seekbar is stopped
}
}
By default, the range of progress is [0,100] in steps of 1.
The older snippet above uses Kotlin synthetic view access. It is kept here for readers maintaining old projects. For new Android projects, prefer View Binding, shown later in this tutorial.
Add a SeekBar to an Android layout and handle progress changes
Following is a step by step guide of what is happening in the above code snippet to use SeekBar.
Step 1: Create a SeekBar in layout file.
<SeekBar
android:id="@+id/seekbarView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
Step 2: Add OnSeekBarChangeListener to the interface list of your Activity.
class MainActivity : /** Other Classes, */OnSeekBarChangeListener {
}
Step 3: Set setOnSeekBarChangeListener to the SeekBar.
seekbarView!!.setOnSeekBarChangeListener(this)
Step 4: We have to override the following three methods of OnSeekBarChangeListener.
override fun onProgressChanged(seekBar: SeekBar, progress: Int,
fromUser: Boolean) {
// called when progress is changed
}
override fun onStartTrackingTouch(seekBar: SeekBar) {
// called when tracking the seekbar is started
}
override fun onStopTrackingTouch(seekBar: SeekBar) {
// called when tracking the seekbar is stopped
}
Get the selected SeekBar value in Kotlin
You can get the current SeekBar value from the progress property. Inside onProgressChanged(), Android also gives the new value through the progress parameter.
val currentValue = seekbarView?.progress ?: 0
Use the fromUser parameter when you need to react only to user dragging and ignore progress changes made by your Kotlin code.
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
if (fromUser) {
progressView?.text = progress.toString()
}
}
Set maximum progress and initial value for Android SeekBar
For a simple range that starts from 0, set android:max and android:progress in the layout. In the following XML, the SeekBar starts at 25 and can move up to 100.
<SeekBar
android:id="@+id/volumeSeekBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="25" />
When you want the visible value to start from a number other than 0, a reliable approach is to map the SeekBar progress to your required value in Kotlin.
val minValue = 10
val maxValue = 60
binding.volumeSeekBar.max = maxValue - minValue
binding.volumeSeekBar.progress = 0
binding.volumeSeekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
val actualValue = minValue + progress
binding.progressValue.text = actualValue.toString()
}
override fun onStartTrackingTouch(seekBar: SeekBar) = Unit
override fun onStopTrackingTouch(seekBar: SeekBar) = Unit
})
Complete Kotlin Android SeekBar example with progress text
Following are the details of the Android Application we created for this example.
| Application Name | SeekBarExample |
| Company name | tutorialkart.com |
| Minimum SDK | API 21: Android 5.0 (Lollipop) |
| Activity | Empty Activity |
You may keep rest of the values as default and create Android Application with Kotlin Support.
The following project files show a working SeekBar example. The TextView named progress displays the current progress value, and the TextView named seekbarStatus displays the drag state.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.tutorialkart.seekbarexample.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="- -"
android:padding="20dp"/>
<TextView
android:id="@+id/seekbarStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="- -"
android:padding="20dp"/>
<SeekBar
android:id="@+id/seekbar"
android:layout_width="match_parent"
android:padding="15dp"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.constraint.ConstraintLayout>
MainActivity.kt
package com.tutorialkart.seekbarexample
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.SeekBar
import android.widget.SeekBar.OnSeekBarChangeListener
import android.widget.TextView
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity(),OnSeekBarChangeListener {
private var progressView: TextView? = null
private var seekbarStatusView: TextView? = null
private var seekbarView: SeekBar? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
progressView = this.progress
seekbarStatusView = this.seekbarStatus
seekbarView = this.seekbar
seekbarView!!.setOnSeekBarChangeListener(this)
}
override fun onProgressChanged(seekBar: SeekBar, progress: Int,
fromUser: Boolean) {
progressView!!.text = progress.toString()
seekbarStatusView!!.text = "Tracking Touch"
}
override fun onStartTrackingTouch(seekBar: SeekBar) {
seekbarStatusView!!.text = "Started Tracking Touch"
}
override fun onStopTrackingTouch(seekBar: SeekBar) {
seekbarStatusView!!.text = "Stopped Tracking Touch"
}
}
Output

Modern AndroidX SeekBar Kotlin example with View Binding
New Android projects usually use AndroidX and View Binding instead of Kotlin synthetic imports. The following version shows the same SeekBar behavior with a generated binding class.
Enable View Binding in build.gradle.kts
android {
buildFeatures {
viewBinding = true
}
}
activity_main.xml for AndroidX
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
android:padding="24dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/progressValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="12dp"
android:text="25" />
<TextView
android:id="@+id/seekbarStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="12dp"
android:text="Move the SeekBar" />
<SeekBar
android:id="@+id/volumeSeekBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="25" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.kt with View Binding
package com.tutorialkart.seekbarexample
import android.os.Bundle
import android.widget.SeekBar
import androidx.appcompat.app.AppCompatActivity
import com.tutorialkart.seekbarexample.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.progressValue.text = binding.volumeSeekBar.progress.toString()
binding.volumeSeekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
binding.progressValue.text = progress.toString()
if (fromUser) {
binding.seekbarStatus.text = "Changed by user"
} else {
binding.seekbarStatus.text = "Changed by code"
}
}
override fun onStartTrackingTouch(seekBar: SeekBar) {
binding.seekbarStatus.text = "Started dragging"
}
override fun onStopTrackingTouch(seekBar: SeekBar) {
binding.seekbarStatus.text = "Stopped dragging"
}
})
}
}
Difference between SeekBar and ProgressBar in Android
A ProgressBar and a SeekBar both represent progress, but they are used for different interaction patterns.
| Widget | How it is used | Typical example |
|---|---|---|
| ProgressBar | Shows progress to the user. The user usually does not control it. | File upload progress, loading progress, download progress. |
| SeekBar | Lets the user change a progress value by dragging the thumb. | Volume control, brightness setting, media seek position. |
Common Android SeekBar Kotlin mistakes and fixes
- Using Kotlin synthetics in a new project: Use View Binding or
findViewById()instead ofkotlinx.android.syntheticin new Android projects. - Ignoring
fromUser: CheckfromUserif your app must respond only when the user changes the SeekBar manually. - Reading the value before the layout is set: Call
setContentView()or inflate View Binding before accessing the SeekBar. - Expecting a non-zero minimum without mapping: If your value range is 10 to 60, set SeekBar progress from 0 to 50 and add 10 in Kotlin.
- Using
!!everywhere: Prefer View Binding or safe calls to avoid unnecessary null pointer errors.
Android SeekBar Kotlin FAQ
What is SeekBar in Android Kotlin?
SeekBar is an Android widget that lets the user select an integer value from a range by dragging a thumb along a track. In Kotlin, you usually handle it with SeekBar.OnSeekBarChangeListener.
How to get value from SeekBar in Kotlin?
Use the progress property. For example, val value = binding.volumeSeekBar.progress gets the current selected value from the SeekBar.
What is the difference between ProgressBar and SeekBar?
ProgressBar is mainly for displaying progress, while SeekBar is for user input. A SeekBar has a draggable thumb so the user can change the value.
How do I set the range of an Android SeekBar?
Set the maximum value using android:max in XML or seekBar.max in Kotlin. For a range that does not start at 0, map the progress value in Kotlin, such as actualValue = minValue + progress.
Should I use Kotlin synthetic imports for SeekBar examples?
Use Kotlin synthetic imports only when maintaining an older project that already uses them. For new Android projects, View Binding is the safer and current approach.
Editorial QA checklist for this Android SeekBar Kotlin tutorial
- The XML layout includes a valid
SeekBarid, width, height, and optionalandroid:maxorandroid:progress. - The Kotlin code reads the selected value from
progressor theonProgressChanged()callback parameter. - The tutorial explains
onStartTrackingTouch(),onStopTrackingTouch(), andfromUserwith SeekBar-specific context. - The legacy synthetic example is clearly separated from the modern View Binding example.
- The output image remains the existing Android SeekBar Kotlin example GIF.
Android SeekBar Kotlin references
- Android Developers: SeekBar
- Android Developers: SeekBar.OnSeekBarChangeListener
- Android Developers: Migrate from Kotlin synthetics to Jetpack view binding
Android SeekBar Kotlin example summary
In this Android Tutorial : Android SeekBar – Kotlin Example, we have learnt how to add a SeekBar to an Android layout, read its progress value in Kotlin, respond to drag callbacks, set a range, and use a modern View Binding approach for new Android projects.
TutorialKart.com