¿Cómo hacer una SeekBar vertical en Android?

¿Puede una barra de búsqueda ser vertical? No soy muy bueno en el diseño de la interfaz de usuario, así que cómo hacer que seekbar sea más bonito, por favor dame algunas plantillas y ejemplos.

Aquí hay una muy buena implementación de barra de búsqueda vertical. Echar un vistazo.

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

Y esta es mi propia implementación para Seekbar vertical e invertida basada en esto

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; } 
  1. Para API 11 y posterior, puede usar los atributos XML de la barra de búsqueda (android: rotation = “270”) para obtener un efecto vertical.

      
  2. Para un nivel API más antiguo (ex API10), solo use la respuesta de Selva:
    https://github.com/AndroSelva/Vertical-SeekBar-Android

Ejemplo de trabajo

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

Allí, pega el código y guárdalo. Ahora úsalo en tu diseño XML:

  

Asegúrese de crear un paquete android.widget y cree VerticalSeekBar.java en este paquete

Tratar:

    

Usé la solución de Selva pero tenía dos tipos de problemas:

  • OnSeekbarChangeListener no funcionó correctamente
  • Establecer el progreso programáticamente no funcionó correctamente.

Arreglé estos dos problemas. Puede encontrar la solución (dentro de mi propio paquete de proyecto) en

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

Hicimos una SeekBar vertical usando android:rotation="270" :

            

Captura de pantalla para la compensación de exposición de la cámara:

enter image description here

Tenga en cuenta que me parece que si cambia el ancho, el ancho del dedo no cambia correctamente. No me tomé el tiempo para arreglarlo, solo lo arreglé para mi caso. Aquí esta lo que hice. No se pudo averiguar cómo contactar al creador original.

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

Esto funcionó para mí, simplemente colóquelo en el diseño que desee.

    

Al mover el pulgar con un EditarTexto, es posible que laSeekbar Vertical setProgress no funcione. El siguiente código puede ayudar:

  @Override public synchronized void setProgress(int progress) { super.setProgress(progress); updateThumb(); } private void updateThumb() { onSizeChanged(getWidth(), getHeight(), 0, 0); } 

Este código de fragmento se encuentra aquí: https://stackoverflow.com/a/33064140/2447726

Empezando

Agregue estas líneas a build.gradle.

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

Uso

Código Java

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

Diseño XML

      

NOTA: android:splitTrack="false" es necesario para Android N +.

Prueba esto

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

En mi caso, utilicé un seekBar ordinario y simplemente volqué el diseño.

seekbark_layout.xml – mi diseño que contiene la barra de búsqueda que tenemos que hacer vertical.

     

activity_main.xml

       

Y en MainActivity giro 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() } } } 

Como resultado, tenemos la barra de búsqueda vertical necesaria: enter image description here

Envuélvalo dentro de FrameLayout para que no haya un problema de Tamaño.