How to make a vertical SeekBar in Android?

匿名 (未验证) 提交于 2019-12-03 01:45:01

问题:

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

回答1:

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


回答2:

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

  2. For older API level (ex API10), only use Selva's answer:
    https://github.com/AndroSelva/Vertical-SeekBar-Android



回答3:

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:

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



回答4:

Try:



回答5:

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



回答6:

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

Screenshot for camera exposure compensation:



回答7:

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


回答8:

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



回答9:

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



回答10:

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

 

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



回答11:

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


回答12:

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.

activity_main.xml

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:



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!