How to make a vertical SeekBar in Android?

AndroidSeekbar

Android Problem Overview


Can a SeekBar be vertical? I am not very good at UI design, so how can I make the SeekBar more beautiful, please give me some templates and examples.

Android Solutions


Solution 1 - Android

  1. For API 11 and later, can use seekbar's XML attributes(android:rotation="270") for vertical effect.

     <SeekBar
     android:id="@+id/seekBar1"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:rotation="270"/>
    
  2. For older API level (ex API10), only use Selva's answer:
    https://github.com/AndroSelva/Vertical-SeekBar-Android

Solution 2 - Android

Here is a very good implementation of vertical seekbar. Have a look.

http://560b.sakura.ne.jp/android/VerticalSlidebarExample.zip

And Here is my own implementation for Vertical and Inverted Seekbar based on this

https://github.com/AndroSelva/Vertical-SeekBar-Android

protected void onDraw(Canvas c) {
    c.rotate(-90);
    c.translate(-getHeight(),0);

    super.onDraw(c);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    if (!isEnabled()) {
        return false;
    }

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
        case MotionEvent.ACTION_MOVE:
        case MotionEvent.ACTION_UP:
        	int i=0;
        	i=getMax() - (int) (getMax() * event.getY() / getHeight());
            setProgress(i);
            Log.i("Progress",getProgress()+"");
            onSizeChanged(getWidth(), getHeight(), 0, 0);
            break;

        case MotionEvent.ACTION_CANCEL:
            break;
    }
    return true;
}

Solution 3 - Android

Working example

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.MotionEvent;

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
   public synchronized void setProgress(int progress)  // it is necessary for calling setProgress on click of a button
   {
    super.setProgress(progress);
    onSizeChanged(getWidth(), getHeight(), 0, 0); 
   }
    @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);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!isEnabled()) {
            return false;
        }

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
            case MotionEvent.ACTION_UP:
                setProgress(getMax() - (int) (getMax() * event.getY() / getHeight()));
                onSizeChanged(getWidth(), getHeight(), 0, 0);
                break;

            case MotionEvent.ACTION_CANCEL:
                break;
        }
        return true;
    }
}

There, paste the code and save it. Now use it in your XML layout:

<android.widget.VerticalSeekBar
  android:id="@+id/seekBar1"
  android:layout_width="wrap_content"
  android:layout_height="200dp"
  />

Make sure to create a package android.widget and create VerticalSeekBar.java under this package

Solution 4 - Android

Try:

<RelativeLayout 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" > 

<SeekBar 
    android:id="@+id/seekBar1" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:rotation="270" 
    /> 

</RelativeLayout> 

Solution 5 - Android

We made a vertical SeekBar by using android:rotation="270":

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="horizontal"
	android:layout_width="match_parent"
	android:layout_height="match_parent">
 
	<SurfaceView
		android:id="@+id/camera_sv_preview"
		android:layout_width="match_parent"
		android:layout_height="match_parent"/>
 
	<LinearLayout
		android:id="@+id/camera_lv_expose"  
		android:layout_width="32dp"
		android:layout_height="200dp"
		android:layout_centerVertical="true"
		android:layout_alignParentRight="true"
		android:layout_marginRight="15dp"
		android:orientation="vertical">
 
		<TextView
			android:id="@+id/camera_tv_expose"
			android:layout_width="32dp"
			android:layout_height="20dp"
			android:textColor="#FFFFFF"
			android:textSize="15sp"
			android:gravity="center"/>
 
		<FrameLayout
			android:layout_width="32dp"
			android:layout_height="180dp"
			android:orientation="vertical">
 
			<SeekBar
				android:id="@+id/camera_sb_expose"
				android:layout_width="180dp"
				android:layout_height="32dp" 
				android:layout_gravity="center"
				android:rotation="270"/>
 
		</FrameLayout>
 
	</LinearLayout>
 
	<TextView
		android:id="@+id/camera_tv_help"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:layout_centerHorizontal="true"
		android:layout_alignParentBottom="true"
		android:layout_marginBottom="20dp"
		android:text="@string/camera_tv"
		android:textColor="#FFFFFF" />
 
</RelativeLayout>

Screenshot for camera exposure compensation:

enter image description here

Solution 6 - Android

I used Selva's solution but had two kinds of issues:

  • OnSeekbarChangeListener did not work properly
  • Setting progress programmatically did not work properly.

I fixed these two issues. You can find the solution (within my own project package) at

https://github.com/jeisfeld/Augendiagnose/blob/master/AugendiagnoseIdea/augendiagnoseLib/src/main/java/de/jeisfeld/augendiagnoselib/components/VerticalSeekBar.java

Solution 7 - Android

This worked for me, just put it into any layout you want to.

<FrameLayout
    android:layout_width="32dp"
    android:layout_height="192dp">

    <SeekBar
        android:layout_width="192dp"
        android:layout_height="32dp"
        android:layout_gravity="center"
        android:rotation="270" />

</FrameLayout>

Solution 8 - Android

Wrap it inside a FrameLayout so that there is no Size issue.

  <FrameLayout
                android:layout_width="@dimen/_20dp"
                android:layout_marginStart="@dimen/_15dp"
                android:layout_marginEnd="@dimen/_15dp"
                android:layout_height="match_parent"
                android:orientation="vertical">
    
                <SeekBar
                    android:layout_width="150dp"
                    android:layout_height="30dp"
                    android:layout_gravity="center"
                    android:rotation="270" />
  </FrameLayout>

Solution 9 - Android

Note, it appears to me that if you change the width the thumb width does not change correctly. I didn't take the time to fix it right, i just fixed it for my case. Here is what i did. Couldn't figure out how to contact the original creator.

public void setThumb(Drawable thumb) {
    if (thumb != null) {
        thumb.setCallback(this);

        // Assuming the thumb drawable is symmetric, set the thumb offset
        // such that the thumb will hang halfway off either edge of the
        // progress bar.
        //This was orginally divided by 2, seems you have to adjust here when you adjust width.
        mThumbOffset = (int)thumb.getIntrinsicHeight();
    }

Solution 10 - Android

When moving the thumb with an EditText, the Vertical Seekbar setProgress may not work. The following code can help:

    @Override
public synchronized void setProgress(int progress) {
    super.setProgress(progress);
    updateThumb();
}

private void updateThumb() {
    onSizeChanged(getWidth(), getHeight(), 0, 0);
}

This snippet code found here: https://stackoverflow.com/a/33064140/2447726

Solution 11 - Android

Getting started

Add these lines to build.gradle.

dependencies {
    compile 'com.h6ah4i.android.widget.verticalseekbar:verticalseekbar:0.7.2'
}

Usage

Java code

public class TestVerticalSeekbar extends AppCompatActivity {
    private SeekBar volumeControl = null;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test_vertical_seekbar);

        volumeControl = (SeekBar) findViewById(R.id.mySeekBar);

        volumeControl.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            int progressChanged = 0;

            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                progressChanged = progress;
            }

            public void onStartTrackingTouch(SeekBar seekBar) {
                // TODO Auto-generated method stub
            }

            public void onStopTrackingTouch(SeekBar seekBar) {
                Toast.makeText(getApplicationContext(), "seek bar progress:" + progressChanged,
                        Toast.LENGTH_SHORT).show();
            }
        });
    }

}

Layout XML

<!-- This library requires pair of the VerticalSeekBar and VerticalSeekBarWrapper classes -->
<com.h6ah4i.android.widget.verticalseekbar.VerticalSeekBarWrapper
    android:layout_width="wrap_content"
    android:layout_height="150dp">
    <com.h6ah4i.android.widget.verticalseekbar.VerticalSeekBar
        android:id="@+id/mySeekBar"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:max="100"
        android:progress="0"
        android:splitTrack="false"
        app:seekBarRotation="CW90" /> <!-- Rotation: CW90 or CW270 -->
</com.h6ah4i.android.widget.verticalseekbar.VerticalSeekBarWrapper>

NOTE: android:splitTrack="false" is required for Android N+.

Solution 12 - Android

Try this

import android.content.Context;
import android.graphics.Canvas;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.SeekBar;

/**
 * Implementation of an easy vertical SeekBar, based on the normal SeekBar.
 */
public class VerticalSeekBar extends SeekBar {
	/**
	 * The angle by which the SeekBar view should be rotated.
	 */
	private static final int ROTATION_ANGLE = -90;

	/**
	 * A change listener registrating start and stop of tracking. Need an own listener because the listener in SeekBar
	 * is private.
	 */
	private OnSeekBarChangeListener mOnSeekBarChangeListener;

	/**
	 * Standard constructor to be implemented for all views.
	 *
	 * @param context The Context the view is running in, through which it can access the current theme, resources, etc.
	 * @see android.view.View#View(Context)
	 */
	public VerticalSeekBar(final Context context) {
		super(context);
	}

	/**
	 * Standard constructor to be implemented for all views.
	 *
	 * @param context The Context the view is running in, through which it can access the current theme, resources, etc.
	 * @param attrs   The attributes of the XML tag that is inflating the view.
	 * @see android.view.View#View(Context, AttributeSet)
	 */
	public VerticalSeekBar(final Context context, final AttributeSet attrs) {
		super(context, attrs);
	}

	/**
	 * Standard constructor to be implemented for all views.
	 *
	 * @param context  The Context the view is running in, through which it can access the current theme, resources, etc.
	 * @param attrs    The attributes of the XML tag that is inflating the view.
	 * @param defStyle An attribute in the current theme that contains a reference to a style resource that supplies default
	 *                 values for the view. Can be 0 to not look for defaults.
	 * @see android.view.View#View(Context, AttributeSet, int)
	 */
	public VerticalSeekBar(final Context context, final AttributeSet attrs, final int defStyle) {
		super(context, attrs, defStyle);
	}

	/*
	 * (non-Javadoc) ${see_to_overridden}
	 */
	@Override
	protected final void onSizeChanged(final int width, final int height, final int oldWidth, final int oldHeight) {
		super.onSizeChanged(height, width, oldHeight, oldWidth);
	}

	/*
	 * (non-Javadoc) ${see_to_overridden}
	 */
	@Override
	protected final synchronized void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
		super.onMeasure(heightMeasureSpec, widthMeasureSpec);
		setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
	}

	/*
	 * (non-Javadoc) ${see_to_overridden}
	 */
	@Override
	protected final void onDraw(@NonNull final Canvas c) {
		c.rotate(ROTATION_ANGLE);
		c.translate(-getHeight(), 0);

		super.onDraw(c);
	}

	/*
	 * (non-Javadoc) ${see_to_overridden}
	 */
	@Override
	public final void setOnSeekBarChangeListener(final OnSeekBarChangeListener listener) {
		// Do not use super for the listener, as this would not set the fromUser flag properly
		mOnSeekBarChangeListener = listener;
	}

	/*
	 * (non-Javadoc) ${see_to_overridden}
	 */
	@Override
	public final boolean onTouchEvent(@NonNull final MotionEvent event) {
		if (!isEnabled()) {
			return false;
		}

		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			setProgressInternally(getMax() - (int) (getMax() * event.getY() / getHeight()), true);
			if (mOnSeekBarChangeListener != null) {
				mOnSeekBarChangeListener.onStartTrackingTouch(this);
			}
			break;

		case MotionEvent.ACTION_MOVE:
			setProgressInternally(getMax() - (int) (getMax() * event.getY() / getHeight()), true);
			break;

		case MotionEvent.ACTION_UP:
			setProgressInternally(getMax() - (int) (getMax() * event.getY() / getHeight()), true);
			if (mOnSeekBarChangeListener != null) {
				mOnSeekBarChangeListener.onStopTrackingTouch(this);
			}
			break;

		case MotionEvent.ACTION_CANCEL:
			if (mOnSeekBarChangeListener != null) {
				mOnSeekBarChangeListener.onStopTrackingTouch(this);
			}
			break;

		default:
			break;
		}

		return true;
	}

	/**
	 * Set the progress by the user. (Unfortunately, Seekbar.setProgressInternally(int, boolean) is not accessible.)
	 *
	 * @param progress the progress.
	 * @param fromUser flag indicating if the change was done by the user.
	 */
	public final void setProgressInternally(final int progress, final boolean fromUser) {
		if (progress != getProgress()) {
			super.setProgress(progress);
			if (mOnSeekBarChangeListener != null) {
				mOnSeekBarChangeListener.onProgressChanged(this, progress, fromUser);
			}
		}
		onSizeChanged(getWidth(), getHeight(), 0, 0);
	}

	/*
	 * (non-Javadoc) ${see_to_overridden}
	 */
	@Override
	public final void setProgress(final int progress) {
		setProgressInternally(progress, false);
	}
}

Solution 13 - Android

I tried in many different ways, but the one which worked for me was. Use Seekbar inside FrameLayout

<FrameLayout
	android:id="@+id/VolumeLayout"
	android:layout_width="match_parent"
	android:layout_height="match_parent"
    android:layout_above="@id/MuteButton"
    android:layout_below="@id/volumeText"
    android:layout_centerInParent="true">
        <SeekBar
        android:id="@+id/volume"
        android:layout_width="500dp"
        android:layout_height="60dp"
        android:layout_gravity="center"
        android:progress="50"
        android:secondaryProgress="40"
        android:progressDrawable="@drawable/seekbar_volume"
        android:secondaryProgressTint="@color/tint_neutral"
        android:thumbTint="@color/tint_neutral"
    />

And in Code.

Setup Pre Draw callback on Seekbar, Where you can change the Width and height of the Seekbar I did this part in c#, so Code i used was

            var volumeSlider = view.FindViewById<SeekBar>(Resource.Id.home_link_volume);

            var volumeFrameLayout = view.FindViewById<FrameLayout>(Resource.Id.linkVolumeFrameLayout);

            void OnPreDrawVolume(object sender, ViewTreeObserver.PreDrawEventArgs e)
            {
                volumeSlider.ViewTreeObserver.PreDraw -= OnPreDrawVolume;
                var h = volumeFrameLayout.Height;
                volumeSlider.Rotation = 270.0f;
                volumeSlider.LayoutParameters.Width = h;
                volumeSlider.RequestLayout();
            }

            volumeSlider.ViewTreeObserver.PreDraw += OnPreDrawVolume;

Here i Add listener to PreDraw Event and when its triggered, I remove the PreDraw so that it doesnt go into Infinite loop.

So when Pre Draw gets executed, I fetch the Height of FrameLayout and assign it to Seekbar. And set the rotation of seekbar to 270. As my seekbar is inside frame Layout and its Gravity is set as Center. I dont need to worry about the Translation. As Seekbar always stay in middle of Frame Layout.

Reason i remove EventHandler is because seekbar.RequestLayout(); Will make this event to be executed again.

Solution 14 - Android

You can do it by yourself - it's now so difficult. Here is an example from my project: https://github.com/AlShevelev/WizardCamera

Let start from settings (attrs.xml).

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="ExpositionBar">
        <attr name="button_icon" format="reference" />
        <attr name="button_icon_size" format="dimension" />

        <attr name="stroke_width" format="dimension" />

        <attr name="stroke_color" format="color" />
        <attr name="button_color" format="color" />
        <attr name="button_color_pressed" format="color" />

        <attr name="min_value" format="float" />
        <attr name="max_value" format="float" />
    </declare-styleable>
</resources>

Here is a couple of utility functions:

fun <T: Comparable<T>>T.fitInRange(range: Range<T>): T =
    when {
        this < range.lower -> range.lower
        this > range.upper -> range.upper
        else -> this
    }

fun Float.reduceToRange(rangeFrom: Range<Float>, rangeTo: Range<Float>): Float =
    when {
        this == rangeFrom.lower -> rangeTo.lower
        this == rangeFrom.upper -> rangeTo.upper
        else -> {
            val placeInRange = (this - rangeFrom.lower) / (rangeFrom.upper - rangeFrom.lower)
            ((rangeTo.upper - rangeTo.lower) * placeInRange) + rangeTo.lower
        }
    }

And at last, but not least - a class for vertical seek bar:

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

    private val drawingRect = RectF(0f, 0f, 0f, 0f)
    private val drawingPaint = Paint(Paint.ANTI_ALIAS_FLAG)

    private val strokeWidth: Float

    @ColorInt
    private val strokeColor: Int
    @ColorInt
    private val buttonFillColor: Int
    @ColorInt
    private val buttonFillColorPressed: Int

    private val icon: VectorDrawable

    private val valuesRange: Range<Float>

    private var centerX = 0f
    private var minY = 0f
    private var maxY = 0f

    private var buttonCenterY = 0f
    private var buttonRadiusExt = 0f
    private var buttonRadiusInt = 0f
    private var buttonMinY = 0f
    private var buttonMaxY = 0f
    private var buttonCenterBoundsRange = Range(0f, 0f)

    private var iconTranslationX = 0f
    private var iconTranslationY = 0f

    private var isInDragMode = false

    private var onValueChangeListener: ((Float) -> Unit)? = null

    private var oldOutputValue = Float.MIN_VALUE

    init {
        val typedArray = context.obtainStyledAttributes(attrs, R.styleable.ExpositionBar)

        icon =  typedArray.getDrawable(R.styleable.ExpositionBar_button_icon) as VectorDrawable
        val iconSize = typedArray.getDimensionPixelSize(R.styleable.ExpositionBar_button_icon_size, 0)
        icon.setBounds(0, 0, iconSize, iconSize)

        strokeWidth = typedArray.getDimensionPixelSize(R.styleable.ExpositionBar_stroke_width, 0).toFloat()
        drawingPaint.strokeWidth = strokeWidth

        strokeColor = typedArray.getColor(R.styleable.ExpositionBar_stroke_color, Color.WHITE)
        buttonFillColor = typedArray.getColor(R.styleable.ExpositionBar_button_color, Color.BLACK)
        buttonFillColorPressed = typedArray.getColor(R.styleable.ExpositionBar_button_color_pressed, Color.BLUE)

        val minValue = typedArray.getFloat(R.styleable.ExpositionBar_min_value, 0f)
        val maxValue = typedArray.getFloat(R.styleable.ExpositionBar_max_value, 0f)
        valuesRange = Range(minValue, maxValue)

        typedArray.recycle()
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)

        drawingRect.right = width.toFloat()
        drawingRect.bottom = height.toFloat()

        buttonCenterY = drawingRect.centerY()

        recalculateDrawingValues()
    }

    override fun onDraw(canvas: Canvas) {
        drawingPaint.color = strokeColor
        drawingPaint.style = Paint.Style.STROKE

        // Draw the center line
        canvas.drawLine(centerX, minY, centerX, buttonMinY, drawingPaint)
        canvas.drawLine(centerX, buttonMaxY, centerX, maxY, drawingPaint)

        // Draw the button
        canvas.drawCircle(centerX, buttonCenterY, buttonRadiusExt, drawingPaint)
        drawingPaint.style = Paint.Style.FILL
        drawingPaint.color = if(isInDragMode) buttonFillColorPressed else buttonFillColor
        canvas.drawCircle(centerX, buttonCenterY, buttonRadiusInt, drawingPaint)

        // Draw button icon
        canvas.translate(iconTranslationX, iconTranslationY)
        icon.draw(canvas)
        canvas.translate(-iconTranslationX, -iconTranslationY)
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent): Boolean {
        if(!isEnabled) {
            return false
        }

        when(event.actionMasked) {
            MotionEvent.ACTION_DOWN -> {
                if(isButtonHit(event.y)){
                    isInDragMode = true
                    invalidate()
                }
            }
            MotionEvent.ACTION_MOVE -> {
                if(isInDragMode) {
                    buttonCenterY = event.y.fitInRange(buttonCenterBoundsRange)
                    recalculateDrawingValues()
                    invalidate()

                    val outputValue = buttonCenterY.reduceToRange(buttonCenterBoundsRange, valuesRange)
                    if (outputValue != oldOutputValue) {
                        onValueChangeListener?.invoke(outputValue)
                        oldOutputValue = outputValue
                    }
                }
            }
            MotionEvent.ACTION_UP,
            MotionEvent.ACTION_CANCEL -> {
                isInDragMode = false
                invalidate()
            }
        }
        return true
    }

    fun setOnValueChangeListener(listener: ((Float) -> Unit)?) {
        onValueChangeListener = listener
    }
    
    private fun recalculateDrawingValues() {
        centerX = drawingRect.left + drawingRect.width()/2
        minY = drawingRect.top
        maxY = drawingRect.bottom

        buttonRadiusExt = drawingRect.width() / 2 - strokeWidth / 2
        buttonRadiusInt = buttonRadiusExt - strokeWidth / 2
        buttonMinY = buttonCenterY - buttonRadiusExt
        buttonMaxY = buttonCenterY + buttonRadiusExt

        val buttonCenterMinY = minY + buttonRadiusExt + strokeWidth / 2
        val buttonCenterMaxY = maxY - buttonRadiusExt - strokeWidth / 2
        buttonCenterBoundsRange = Range(buttonCenterMinY, buttonCenterMaxY)

        iconTranslationX = centerX - icon.bounds.width() / 2
        iconTranslationY = buttonCenterY - icon.bounds.height() / 2
    }

    private fun isButtonHit(y: Float): Boolean {
        return y >= buttonMinY && y <= buttonMaxY
    }
}

You can use it as shown here:

<com.shevelev.wizard_camera.main_activity.view.widgets.ExpositionBar
    android:id="@+id/expositionBar"
    android:layout_width="@dimen/mainButtonSize"
    android:layout_height="300dp"
    android:layout_gravity="end|center_vertical"

    android:layout_marginEnd="@dimen/marginNormal"
    android:layout_marginBottom="26dp"

    app:button_icon = "@drawable/ic_brightness"
    app:button_icon_size = "@dimen/toolButtonIconSize"
    app:stroke_width = "@dimen/strokeWidthNormal"
    app:stroke_color = "@color/mainButtonsForeground"
    app:button_color = "@color/mainButtonsBackground"
    app:button_color_pressed = "@color/mainButtonsBackgroundPressed"
    app:min_value="-100"
    app:max_value="100"
/>

Voila!

Solution 15 - Android

In my case, I used an ordinary seekBar and just flipped out the layout.

seekbark_layout.xml - my layout that containts seekbar which we need to make vertical.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rootView"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

<SeekBar
	android:id="@+id/seekBar"
	android:layout_width="match_parent"
	android:layout_height="50dp"
	android:layout_alignParentBottom="true"/>

</RelativeLayout>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    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.vgfit.seekbarexample.MainActivity">

<View
	android:id="@+id/headerView"
	android:layout_width="match_parent"
	android:layout_height="100dp"
	android:background="@color/colorAccent"/>

<View
	android:id="@+id/bottomView"
	android:layout_width="match_parent"
	android:layout_height="100dp"
	android:layout_alignParentBottom="true"
	android:background="@color/colorAccent"/>

<include
	layout="@layout/seekbar_layout"
	android:layout_width="match_parent"
	android:layout_height="match_parent"
	android:layout_above="@id/bottomView"
	android:layout_below="@id/headerView"/>

 </RelativeLayout>

And in MainActivity I rotate seekbar_layout:

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.widget.RelativeLayout
import kotlinx.android.synthetic.main.seekbar_layout.*


class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    rootView.post {
        val w = rootView.width
        val h = rootView.height

        rootView.rotation = 270.0f
        rootView.translationX = ((w - h) / 2).toFloat()
        rootView.translationY = ((h - w) / 2).toFloat()

        val lp = rootView.layoutParams as RelativeLayout.LayoutParams
        lp.height = w
        lp.width = h
        rootView.requestLayout()
    }
}
}

As a result we have necessary vertical seekbar: enter image description here

Solution 16 - Android

By using RotateLayout, having vertical SeekBar is a breeze. Just wrap that horrible SeekBar into it and Bob is your uncle:

<com.github.rongi.rotate_layout.layout.RotateLayout
	xmlns:app="http://schemas.android.com/apk/res-auto"
	android:layout_width="wrap_content"
	android:layout_height="wrap_content"
	app:angle="-90"
	>

		<androidx.appcompat.widget.AppCompatSeekBar
			android:layout_width="match_parent"
			android:layout_height="wrap_content"
		/>

</com.github.rongi.rotate_layout.layout.RotateLayout>

https://github.com/rongi/rotate-layout

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionChrisView Question on Stackoverflow
Solution 1 - AndroidSaturnView Answer on Stackoverflow
Solution 2 - AndroidAndro SelvaView Answer on Stackoverflow
Solution 3 - AndroidZar E AhmerView Answer on Stackoverflow
Solution 4 - AndroidBalaji GunasekarView Answer on Stackoverflow
Solution 5 - AndroidMaxim MikhisorView Answer on Stackoverflow
Solution 6 - AndroidJörg EisfeldView Answer on Stackoverflow
Solution 7 - AndroidNickView Answer on Stackoverflow
Solution 8 - AndroidAbhishek SenguptaView Answer on Stackoverflow
Solution 9 - Androiduser602622View Answer on Stackoverflow
Solution 10 - AndroidGuy WestView Answer on Stackoverflow
Solution 11 - AndroidPhadadevView Answer on Stackoverflow
Solution 12 - AndroidSaef MythView Answer on Stackoverflow
Solution 13 - Androidsoan sainiView Answer on Stackoverflow
Solution 14 - AndroidAlex ShevelevView Answer on Stackoverflow
Solution 15 - AndroidVdovinView Answer on Stackoverflow
Solution 16 - AndroidPeterView Answer on Stackoverflow