2

I have to implement the below seek bar as shown below.enter image description here

The left side round thumb icon can be dragged and can be placed to each corresponding numbers. The number's remain constant, only the thumb icon can be dragged to each position using finger. How can I make the thumb alone scroll ?

I'm Coder
  • 125
  • 2
  • 13

2 Answers2

2

For the verical SeekBar, you can use the custom view that is here without much, if any, modification.

Update: Without modification except replace

int i=0;
i=getMax() - (int) (getMax() * event.getY() / getHeight());

with

int i = getMax() - (int) (getMax() * (event.getY() - getPaddingEnd()) / (getHeight() - getPaddingEnd()));

The SeekBar thumb can be defined as follows:

seekbar_thumb.xml

<shape 
    android:shape="oval">
    <solid android:color="@android:color/white" />
    <size
        android:width="24dp"
        android:height="24dp" />
</shape>

Together these give us the following:

enter image description here

The goal now is to overlay what we have with the text. We can do this with a ConstraintLayout with nine TextViews. We will set the top and bottom TextViews and place the intervening TextView within a vertical chain. Embedded comments give more information about the layout.

activity_main.xml

<androidx.constraintlayout.widget.
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!--    Since the SeekBar is rotated -90 degrees by the custom view, paddingEnd becomes
            the padding from the top of the rotated view.
    -->
    <com.example.verticalseekbar.VerticalSeekBar
        android:id="@+id/seekbar"
        android:layout_width="30dp"
        android:layout_height="350dp"
        android:layout_marginStart="36dp"
        android:background="@drawable/seekbar_background"
        android:max="9"
        android:min="1"
        android:paddingEnd="48dp"
        android:progressDrawable="@null"
        android:thumb="@drawable/seekbar_thumb"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <!--    The SeekBar has an implicit left padding of 16dp, so the top margin for the top line
            of text is 48dp - 16dp == 36dp (SeekBar top padding less the left padding of this view.
            This value and the positioning of the top and bottom TextViews might be better under
            program control rather than specifying them here.
    -->
    <TextView
        android:id="@+id/textView9"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="36dp"
        android:paddingStart="8dp"
        android:text="9     Incredible"
        android:textSize="20sp"
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="@id/seekbar"
        app:layout_constraintTop_toTopOf="@+id/seekbar"
        app:layout_constraintVertical_chainStyle="spread_inside" />

    <TextView
        android:id="@+id/textView8"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingStart="8dp"
        android:text="8     Great"
        android:textSize="20sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toTopOf="@+id/textView7"
        app:layout_constraintStart_toStartOf="@id/seekbar"
        app:layout_constraintTop_toBottomOf="@+id/textView9" />

    <TextView
        android:id="@+id/textView7"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingStart="8dp"
        android:text="7     Good"
        android:textSize="20sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toTopOf="@+id/textView6"
        app:layout_constraintStart_toStartOf="@id/seekbar"
        app:layout_constraintTop_toBottomOf="@+id/textView8" />

    <TextView
        android:id="@+id/textView6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingStart="8dp"
        android:text="6     Above Average"
        android:textSize="20sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toTopOf="@+id/textView5"
        app:layout_constraintStart_toStartOf="@id/seekbar"
        app:layout_constraintTop_toBottomOf="@+id/textView7" />

    <TextView
        android:id="@+id/textView5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingStart="8dp"
        android:text="5     Average (I'd drink it if it's free)"
        android:textSize="20sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toTopOf="@+id/textView4"
        app:layout_constraintStart_toStartOf="@id/seekbar"
        app:layout_constraintTop_toBottomOf="@+id/textView6" />

    <TextView
        android:id="@+id/textView4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingStart="8dp"
        android:text="4     Below Average"
        android:textSize="20sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toTopOf="@+id/textView3"
        app:layout_constraintStart_toStartOf="@id/seekbar"
        app:layout_constraintTop_toBottomOf="@+id/textView5" />

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingStart="8dp"
        android:text="3     Poor"
        android:textSize="20sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toTopOf="@+id/textView2"
        app:layout_constraintStart_toStartOf="@id/seekbar"
        app:layout_constraintTop_toBottomOf="@+id/textView4" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingStart="8dp"
        android:text="2     Terrible"
        android:textSize="20sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toTopOf="@+id/textView1"
        app:layout_constraintStart_toStartOf="@id/seekbar"
        app:layout_constraintTop_toBottomOf="@+id/textView3" />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:layout_marginBottom="4dp"
        android:paddingStart="8dp"
        android:text="1     Undrinkable"
        android:textSize="20sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toBottomOf="@id/seekbar"
        app:layout_constraintStart_toStartOf="@id/seekbar" />

</androidx.constraintlayout.widget.ConstraintLayout>

enter image description here

Cheticamp
  • 61,413
  • 10
  • 78
  • 131
1

Please check below code for vertical seeker in android

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;
    }
}

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

<android.widget.VerticalSeekBar
  android:id="@+id/seekBar"
  android:layout_width="wrap_content"
  android:layout_height="400dp"
  />
Sumit Kumar
  • 263
  • 1
  • 6