So! More than likely you’ve come here wanting source code for a fully working Vertical SeekBar, or you’re a friend who knows little about programming but happened to click on my Facebook or Twitter post. I’ve made this quick explanation/tutorial in frustration over the lack of working solutions found on Google and StackOverflow – They mostly worked, but there was always something wrong with each implementation; the progress didn’t update correctly, the bar didn’t draw correctly, the thumb didn’t unhighlight, or maybe it just didn’t look right. This solution seems to solve all of this.

It’s not the best code in the world, but it works.
Here is the important parts of the VerticalSeekBar class. I merged a few solutions I found to make this. The goal was to make VerticalSeekBar behave exactly like a normal horizontal SeekBar.
public class VerticalSeekBar extends SeekBar {
public VerticalSeekBar(Context context) {
super(context);
}
public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public VerticalSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(h, w, oldh, oldw);
}
@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
protected void onDraw(Canvas c) {
c.rotate(-90);
c.translate(-getHeight(), 0);
super.onDraw(c);
}
private OnSeekBarChangeListener onChangeListener;
@Override
public void setOnSeekBarChangeListener(OnSeekBarChangeListener onChangeListener){
this.onChangeListener = onChangeListener;
}
private int lastProgress = 0;
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled()) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
onChangeListener.onStartTrackingTouch(this);
setPressed(true);
setSelected(true);
break;
case MotionEvent.ACTION_MOVE:
super.onTouchEvent(event);
int progress = getMax() - (int) (getMax() * event.getY() / getHeight());
// Ensure progress stays within boundaries
if(progress < 0) {progress = 0;}
if(progress > getMax()) {progress = getMax();}
setProgress(progress); // Draw progress
if(progress != lastProgress) {
// Only enact listener if the progress has actually changed
lastProgress = progress;
onChangeListener.onProgressChanged(this, progress, true);
}
onSizeChanged(getWidth(), getHeight() , 0, 0);
setPressed(true);
setSelected(true);
break;
case MotionEvent.ACTION_UP:
onChangeListener.onStopTrackingTouch(this);
setPressed(false);
setSelected(false);
break;
case MotionEvent.ACTION_CANCEL:
super.onTouchEvent(event);
setPressed(false);
setSelected(false);
break;
}
return true;
}
public synchronized void setProgressAndThumb(int progress) {
setProgress(progress);
onSizeChanged(getWidth(), getHeight() , 0, 0);
if(progress != lastProgress) {
// Only enact listener if the progress has actually changed
lastProgress = progress;
onChangeListener.onProgressChanged(this, progress, true);
}
}
public synchronized void setMaximum(int maximum) {
setMax(maximum);
}
public synchronized int getMaximum() {
return getMax();
}
}
I then inserted the VerticalSeekBar inside a LinearLayout like so:
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:orientation="vertical" >
<com.safetyculture.jsadroidtablet.VerticalSeekBar
android:id="@+id/calculatorVerticalSeekBar"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="bottom"
android:max="4"
android:progress="2" />
</LinearLayout>
NOTE: In this implementation you must set an OnSeekBarChangeListener for the VerticalSeekBar before using it in the app, otherwise interacting with the VerticalSeekBar will produce NullPointerException.
NOTE2: If you wish to change the progress manually/programmatically rather than through the UI Motion Events, you will need to call setProgressAndThumb(progress), otherwise the thumb doesn’t update correctly.

Where do you put the java code?Everyone is providing a solution but not really saying where to place the code or even how to used it.
The “VerticalSeekBar” class code, just throw that into it’s own class file, like I have here: http://d.pr/i/drMq
Using it in XML is done by using the XML code I provided, except change “com.safetyculture.jsadroidtablet.VerticalSeekBar” to whatever your package name is where the class is located (eg “com.your.package.here.VerticalSeekBar”)
If you then wanted to access the layout element in the code, it can be done the same way normal layout elements are accessed:
VerticalSeekBar variableName = (VerticalSeekBar)layoutName.findViewById(R.id.verticalSeekBarId);
Replace variableName with a name for it.
Replace layoutName with the layout you’re using.
Replace vericalSeekBarId with the id you gave it in the XML.
I hope that answers your question :)
Hi, i’ve implemented your vertical seekbar and works great, but i have experienced an issue when using buttons to change the progress value, i have two buttons:
top button sets current progress += 1
bottom button set to current progress value -= 1
and when are pressed the thumb indicator gets always at bottom of the layout contanier of the seekbar, i think is cause i must adjust the thumb “y” position but i cant find how do it, thanks for your help.
I see what you’re trying to do.
I think the best way will be to create a simulated touch Event and pass it to the dispatchTouchEvent(MotionEvent event) method of the VerticalSeekBar, when you want to change the progress manually. ( This way you just send a MotionEvent that is of the type MotionEvent.ACTION_MOVE )
So, inside your top button’s OnClick listener code, make it call verticalSeekBar.dispatchTouchEvent(event) with the following event:
I’m not quite sure what you’ll need to set ‘x’ and ‘y’ to, hopefully you’ll get it with some trial and error. Also, perhaps the methods verticalSeekBar.getScrollX() and verticalSeekBar.getScrollY() will be of use.
Hope I helped.
Thanks, i solved just calling the setProgressAndThumb(progress) method inside your VerticalSeekBar class, if someone else gets in the same situation here is how i solved it:
// Creating the vertical Seekbar
vs = (VerticalSeekBar) findViewById(R.id.vs);
// Snippet to increase progress value manually from a button
….
if ( !(vs.getProgress() + 1 > vs.getMax()) ){
int newProgresValue = vs.getProgress() + 1;
vs.setProgressAndThumb( newProgresValue );
}
….
Thanks again :D !!!
Ah! I completely forgot about the setProgressAndThumb method. You may also want to set the lastProgress class variable inside the method (I’ve edited the code to include it)
Works great! Thank you.
It does not correctly handle padding.
You have to set paddingLeft to actually get paddingBottom.
Besides that, the padding isn’t being taken into account when calculating the position of the slider (i.e. the slider position does not correspond to the touch position)
How would you suggest going about this?
The slider still seems to work for the most/important part, but I think I know what you mean.
I’m afraid you’d have to reimplement vital parts of ProgressBar, AbsSeekBar and SeekBar …
Hi!
I am newie to Android and I want to use your seekbar. But I am having problems when I am trying to use the onStartTrackingTouch and onStopTrackingTouch methids. It seems that nothing happens when I click and I release the seebar.
Thanks!
Hi again, forget it! I solve it!
Thanks! :)
Hi Julius,
How did you manage to solve this problem.. I’m having exactly the same thing.
Thanks!
hi,
when I use your code in Android, I got the correct vertical seek bar which starts from bottom (progress 0 ) to top (progress max). I actually need an inversely vertical seek bar which starts from top (progress 0) to bottom. I tried to use
c.rotate(90);
c.translate(0,-getHeight());
but I got the thumb and the progess bar separately, not nicely together like with your code.
Could you show me what I did wrong here? Thanks!
Try:
c.rotate(90);
c.translate(0,-getWidth());
Thanks a lot for the code, it was very helpful.
But i was having a problem when using more than one SeekBar at a time and using the method setProgressAndThumb. One SeekBar was always OK, but the others the thumb position wouldn’t match the progress position. So i put everything of the setProgressAndThumb method inside a
this.post(new Runnable() {
public void run() {
}
});
After that it worked fine. I think that happened because i was using this method of the SeekBars at the same time. Just trying to contribute with your work and make it better to everyone