In this tutorial, we’ll discuss and implement SeekBar in our Android Application using Kotlin.
What is Android SeekBar?
SeekBar is a UI element that is an extension of the ProgressBar.
SeekBar adds a draggable thumb to the ProgressBar. It is commonly used in music apps to provide volume control.
SeekBar is like a scale with an upper and lower limit and every step is a single unit.
SeekBar XML Attributes
Some of the important XML attributes of SeekBar are:
android:minWidth/maxWidth/minHeight/maxHeight
: these attributes are used to set the dimensions of the seekbar view. They don’t change the thickness of the SeekBar.android:max/min
: The upper/lower limit of the SeekBar. The android:min is available from Android SDK 26 and above.android:progress
: The current value of the thumb position.android:progressTint
: Here we pass the color for the progress to the left of the thumb position.android:progressBackgroundTint
: This color is displayed for the SeekBar background, to the right of the thumb.android:thumb
: Here we can pass a custom drawable that will act as the thumb of the seek bar.android:thumbTint
: color of the thumb.android:thumbOffset
: The distance between the thumb and the current progress indp
. A negative value shifts the thumb to the right of the progress. A positive one shifts it to the left.style
: it’s used to set custom/predefined styles on the SeekBar. There is a popular seekbar style – “Discrete” – which breaks the progress into discrete intervals.android:tickMark
: Here we pass a drawable, which acts as breakpoints on the SeekBar. The number of breakpoints/tickMarks is equal to android:max.android:tickMarkTint
: used to set a color on the tickMark drawable.android:splitTrack
: This expects a boolean value. By default on Android Lollipop and above this is true. It splits the Seekbar track into two parts – left and right of the SeekBar. This isn’t always visible in white background activities.
Creating SeekBar in Kotlin
We can implement the SeekBar.OnSeekBarChangeListener
interface to create SeekBar programatically. We have to implement the following three Kotlin functions.
1 2 3 4 5 6 |
fun onProgressChanged(p0: SeekBar?, p1: Int, p2: Boolean) fun onStartTrackingTouch(p0: SeekBar?) fun onStopTrackingTouch(p0: SeekBar?) |
SeekBar Examples
Let’s look at the different types of SeekBar by setting the above properties.
1. Simple SeekBar
1 2 3 4 5 6 |
<SeekBar android:id="@+id/seekbar1" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="8dp" /> |
2. SeekBar with Progress Tint Color
1 2 3 4 5 6 7 8 9 10 11 |
<SeekBar android:id="@+id/seekbar2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:max="50" android:minWidth="100dp" android:padding="8dp" android:progress="10" android:progressBackgroundTint="@android:color/black" android:progressTint="@color/colorPrimaryDark" /> |
3. SeekBar with Thumb Tint Color And Offset
1 2 3 4 5 6 7 8 9 10 11 12 |
<SeekBar android:id="@+id/seekbar3" android:layout_width="match_parent" android:layout_height="wrap_content" android:max="50" android:padding="8dp" android:progress="10" android:progressBackgroundTint="@android:color/holo_green_light" android:progressTint="@android:color/black" android:thumbOffset="-20dp" android:thumbTint="@color/colorPrimary" /> |
4. SeekBar with TickMarks
1 2 3 4 5 6 7 8 9 10 11 12 |
<SeekBar android:id="@+id/seekbar4" android:layout_width="match_parent" android:layout_height="wrap_content" android:max="4" android:padding="8dp" android:progress="1" android:progressTint="@android:color/holo_green_light" android:thumbTint="@color/colorPrimary" android:tickMark="@drawable/tickmark" android:tickMarkTint="@color/colorAccent" /> |
The tickmark.xml drawable is given below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:bottom="-6dp" android:left="-3dp" android:top="-6dp"> <shape android:shape="rectangle"> <solid android:color="@color/colorPrimary" /> <stroke android:width="2dp" android:color="#1fc78c" /> </shape> </item> </layer-list> |
5. SeekBar with Custom Style
Here we set Discrete
style with different intervals (max value).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<SeekBar android:id="@+id/seekbar5" style="@android:style/Widget.Material.SeekBar.Discrete" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="8dp" /> <SeekBar android:id="@+id/seekbar6" style="@android:style/Widget.Material.SeekBar.Discrete" android:layout_width="match_parent" android:layout_height="wrap_content" android:max="10" android:padding="8dp" /> |
6. SeekBar with Split Track
The first one has a Split track enabled by default. The second one does not.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<SeekBar android:id="@+id/seekbar7" android:layout_width="match_parent" android:layout_height="wrap_content" android:max="50" android:padding="8dp" android:progress="10" android:thumbTint="@color/colorPrimary" android:tickMark="@android:drawable/checkbox_on_background" android:tickMarkTint="@android:color/black" /> <SeekBar android:id="@+id/seekbar8" android:layout_width="match_parent" android:layout_height="wrap_content" android:max="50" android:padding="8dp" android:progress="10" android:splitTrack="false" android:thumbTint="@color/colorPrimary" android:tickMark="@android:drawable/checkbox_on_background" android:tickMarkTint="@android:color/black" /> |
Android SeekBar Kotlin Project Structure
1. Activity XML Code
The code for the activity_main.xml layout is as follows.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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" android:layout_margin="16dp" android:id="@+id/linearLayout" android:gravity="center" android:orientation="vertical" tools:context=".MainActivity"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="0" android:textSize="32sp" /> <SeekBar android:id="@+id/seekbar1" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="8dp" /> <SeekBar android:id="@+id/seekbar2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:max="50" android:minWidth="100dp" android:padding="8dp" android:progress="10" android:progressBackgroundTint="@android:color/black" android:progressTint="@color/colorPrimaryDark" /> <SeekBar android:id="@+id/seekbar3" android:layout_width="match_parent" android:layout_height="wrap_content" android:max="50" android:padding="8dp" android:progress="10" android:progressBackgroundTint="@android:color/holo_green_light" android:progressTint="@android:color/black" android:thumbOffset="-20dp" android:thumbTint="@color/colorPrimary" /> <SeekBar android:id="@+id/seekbar4" android:layout_width="match_parent" android:layout_height="wrap_content" android:max="4" android:padding="8dp" android:progress="1" android:progressTint="@android:color/holo_green_light" android:thumbTint="@color/colorPrimary" android:tickMark="@drawable/tickmark" android:tickMarkTint="@color/colorAccent" /> <SeekBar android:id="@+id/seekbar5" style="@android:style/Widget.Material.SeekBar.Discrete" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="8dp" /> <SeekBar android:id="@+id/seekbar6" style="@android:style/Widget.Material.SeekBar.Discrete" android:layout_width="match_parent" android:layout_height="wrap_content" android:max="10" android:padding="8dp" /> <SeekBar android:id="@+id/seekbar7" android:layout_width="match_parent" android:layout_height="wrap_content" android:max="50" android:padding="8dp" android:progress="10" android:thumbTint="@color/colorPrimary" android:tickMark="@android:drawable/checkbox_on_background" android:tickMarkTint="@android:color/black" /> <SeekBar android:id="@+id/seekbar8" android:layout_width="match_parent" android:layout_height="wrap_content" android:max="50" android:padding="8dp" android:progress="10" android:splitTrack="false" android:thumbTint="@color/colorPrimary" android:tickMark="@android:drawable/checkbox_on_background" android:tickMarkTint="@android:color/black" /> <SeekBar android:id="@+id/seekbar9" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="8dp" android:splitTrack="false" android:thumb="@mipmap/ic_launcher" /> </LinearLayout> |
We’ve created a custom thumb in the last SeekBar.
custom_thumb.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item> <shape> <size android:width="10dp" android:height="10dp" /> <solid android:color="@android:color/transparent" /> </shape> </item> <item android:drawable="@mipmap/ic_launcher" /> </layer-list> |
2. Activity Kotlin Code
The Kotlin code for the MainActivity.kt class is as follows.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
package net.androidly.androidlyseekbar import android.support.v7.app.AppCompatActivity import android.os.Bundle import android.view.ViewGroup import android.widget.LinearLayout import android.widget.SeekBar import kotlinx.android.synthetic.main.activity_main.* import android.graphics.PorterDuff import android.support.v4.content.ContextCompat class MainActivity : AppCompatActivity(), SeekBar.OnSeekBarChangeListener { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val seekbar = SeekBar(this) val layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) layoutParams.setMargins(30, 30, 30, 30) seekbar.layoutParams = layoutParams seekbar.progressDrawable.setColorFilter(ContextCompat.getColor(this, R.color.switch_thumb_normal_material_dark), PorterDuff.Mode.SRC_ATOP) seekbar.setBackgroundColor(ContextCompat.getColor(this,android.R.color.darker_gray)) seekbar.setOnSeekBarChangeListener(this) linearLayout.addView(seekbar) seekbar1.setOnSeekBarChangeListener(this) seekbar2.setOnSeekBarChangeListener(this) seekbar3.setOnSeekBarChangeListener(this) seekbar4.setOnSeekBarChangeListener(this) seekbar5.setOnSeekBarChangeListener(this) seekbar6.setOnSeekBarChangeListener(this) seekbar7.setOnSeekBarChangeListener(this) seekbar8.setOnSeekBarChangeListener(this) seekbar9.setOnSeekBarChangeListener(this) } override fun onProgressChanged(p0: SeekBar?, p1: Int, p2: Boolean) { textView.text = "$p1" } override fun onStartTrackingTouch(p0: SeekBar?) { } override fun onStopTrackingTouch(p0: SeekBar?) { } } |
In the above code, we’ve created a SeekBar in Kotlin and added it to the LinearLayout.
We’ve set the SeekBar change listener on each of them. The p1
represents the current progress value which is the same as seekBar.getProgress()
. We are setting this value in the TextView.
Output: