2010-10-13 16 views
26

Estoy tratando de usar una ProgressBar como una pantalla de medición. Pensé que sería una tarea fácil y pensé que ProgressBar tenía una propiedad para ser vertical, pero no veo nada.Android: ¿configura una ProgressBar para que sea una barra vertical en lugar de horizontal?

Además, me gustaría poder mostrar una regla como indicador a lo largo del lado de la barra para indicar claramente el nivel actual.

Sugerencias apreciadas - ¡Gracias!

+0

Aviso mi nuevo [respuesta] (http://stackoverflow.com/questions/3926395/android-set-a-progressbar- to-be-a-vertical-bar-instead-of-horizontal/40538069 # 40538069), espero que ayude a alguien :) –

+0

http://android-coding.blogspot.co.uk/2013/02/implement-vertical- progressbar.html – Masoud

Respuesta

3

Las barras de progreso vertical no son compatibles por defecto.

+0

¡Ratas! ¡Gracias por la respuesta! – bursk

+22

+1 para la respuesta, -1 para cuál es la respuesta .... :) –

+20

** @ Romain Guy ** ¿No eres un desarrollador de Android en Google? ¿No puedes * por favor * hacer que todo tipo de barras de progreso apoyen la colocación vertical? Creo que es una expectativa bastante obvia de los desarrolladores de UI. –

1

Para utilizar ProgressBar y hacerlo vertical, debe crear su propia Vista personalizada ampliando la vista ProgressBar y anulando el método onDraw(). Esto le permitirá dibujarlo en una orientación inversa. Eche un vistazo al source code del ProgressBar.onDraw() (ubicado en la parte inferior del enlace) para obtener ayuda sobre cómo hacer esto. En el mejor de los casos, solo tendrá que cambiar algunas variables xe y.

48

Recientemente me encontré con la necesidad de una barra de progreso vertical, pero no pude encontrar una solución utilizando el widget existente Barra de progreso. Las soluciones que encontré generalmente requieren una extensión de la barra de progreso actual o una clase completamente nueva en sí misma. No estaba convencido de implementar una nueva clase para lograr un cambio de orientación simple.

Este artículo presenta una solución simple, elegante y lo más importante, una solución sin cortes para lograr una barra de progreso vertical. Voy a omitir la explicación y simplemente proporcionar una solución de cortador de galletas. Si necesita más información, no dude en ponerse en contacto conmigo o dejar un comentario a continuación.

Cree un xml en su carpeta dibujable (no drawable-hdpi o drawable-mdpi - colóquelo en drawable). Para este ejemplo llamo a mi xml vertical_progress_bar.xml

Esto es lo que coloque en el archivo xml:

<?xml version="1.0" encoding="utf-8"?> 
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:id="@android:id/background"> 
    <shape> 
     <corners android:radius="5dip" /> 
     <gradient 
     android:startColor="#ff9d9e9d" 
     android:centerColor="#ff5a5d5a" 
     android:centerY="0.75" 
     android:endColor="#ff747674" 
     android:angle="180" 
     /> 
    </shape> 
    </item> 
    <item android:id="@android:id/secondaryProgress"> 
    <clip android:clipOrientation="vertical" android:gravity="bottom"> 
     <shape> 
     <corners android:radius="5dip" /> 
     <gradient 
      android:startColor="#80ffd300" 
      android:centerColor="#80ffb600" 
      android:centerY="0.75" 
      android:endColor="#a0ffcb00" 
      android:angle="180" 
     /> 
     </shape> 
    </clip> 
    </item> 
    <item android:id="@android:id/progress"> 
    <clip android:clipOrientation="vertical" android:gravity="bottom"> 
     <shape> 
     <corners android:radius="5dip" /> 
     <gradient 
      android:startColor="#ffffd300" 
      android:centerColor="#ffffb600" 
      android:centerY="0.75" 
      android:endColor="#ffffcb00" 
      android:angle="180" 
     /> 
     </shape> 
    </clip> 
</item> 
</layer-list> 

crear un archivo XML denominado styles.xml y colocarlo en res/valores. Si su proyecto ya contiene styles.xml en res/values, omita este paso.

modificar su archivo styles.xml y añadir el siguiente código al final del archivo:

<style name="Widget"> 
</style> 
<style name="Widget.ProgressBar"> 
    <item name="android:indeterminateOnly">true</item> 
    <item name="android:indeterminateBehavior">repeat</item> 
    <item name="android:indeterminateDuration">3500</item> 
    <item name="android:minWidth">48dip</item> 
    <item name="android:maxWidth">48dip</item> 
    <item name="android:minHeight">48dip</item> 
    <item name="android:maxHeight">48dip</item> 
</style> 
<style name="Widget.ProgressBar.Vertical"> 
    <item name="android:indeterminateOnly">false</item> 
    <item name="android:progressDrawable">@drawable/progress_bar_vertical</item> 
    <item name="android:indeterminateDrawable">@android:drawable/progress_indeterminate_horizontal</item> 
    <item name="android:minWidth">1dip</item> 
    <item name="android:maxWidth">12dip</item> 
</style> 

Añadir su nueva barra de progreso vertical para su diseño. He aquí un ejemplo:

<ProgressBar 
    android:id="@+id/vertical_progressbar" 
    android:layout_width="12dip" 
    android:layout_height="300dip" 
    style="@style/Widget.ProgressBar.Vertical" 
/> 

Eso debería ser todo lo que necesita hacer para hacer uso de una barra de progreso vertical en su proyecto. Opcionalmente, puede tener imágenes personalizables de nueve parches que está utilizando para la barra de progreso. Debe realizar los cambios apropiados en el archivo progress_bar_vertical.xml. ¡Espero que esto lo ayude en su proyecto!

+0

el ejemplo en su publicación de blog está incompleto, hay usuarios haciendo preguntas a las que no ha respondido. – LairdPleng

+4

+1 para la sugerencia con respecto al atributo 'clipOrientation'. – sven

+3

@jagsaund no hay ningún archivo en el enlace dado –

27

Tienes que crear tu propia barra de progreso personalizada.

En su xml añadir este diseño:

<com.example.component.VerticalProgressBar 
     style="?android:attr/progressBarStyleHorizontal" 
     android:id="@+id/verticalRatingBar1" 
     android:layout_width="wrap_content" 
     android:progress="50" 
     android:layout_height="fill_parent" /> 

VerticalProgressBar.java

public class VerticalProgressBar extends ProgressBar{ 
    private int x, y, z, w; 

    @Override 
    protected void drawableStateChanged() { 
     // TODO Auto-generated method stub 
     super.drawableStateChanged(); 
    } 

    public VerticalProgressBar(Context context) { 
     super(context); 
    } 

    public VerticalProgressBar(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
    } 

    public VerticalProgressBar(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    protected void onSizeChanged(int w, int h, int oldw, int oldh) { 
     super.onSizeChanged(h, w, oldh, oldw); 
     this.x = w; 
     this.y = h; 
     this.z = oldw; 
     this.w = oldh; 
    } 

    @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: 

      setSelected(true); 
      setPressed(true); 
      break; 
     case MotionEvent.ACTION_MOVE: 
      setProgress(getMax() 
        - (int) (getMax() * event.getY()/getHeight())); 
      onSizeChanged(getWidth(), getHeight(), 0, 0); 

      break; 
     case MotionEvent.ACTION_UP: 
      setSelected(false); 
      setPressed(false); 
      break; 

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

    @Override 
    public synchronized void setProgress(int progress) { 

     if (progress >= 0) 
      super.setProgress(progress); 

     else 
      super.setProgress(0); 
     onSizeChanged(x, y, z, w); 

    } 
} 

O: Jagsaund solución también está siendo perfecta.

+0

Gracias Sr.Drugo! –

+1

Lamentablemente, la barra de progreso no se actualiza correctamente después de alcanzar una altura que es igual al ancho de la barra (comenzando desde la parte superior), creo que algunos x/y se mezclaron pero no pude encontrar una solución fácil, usé jagsaund solución –

+2

Add invalidate(); después de onSizeChanged(); para evitar los problemas de representación mencionados. –

0

Tengo el problema exacto. Hacer una clase personalizada (extendiendo ProgressBar) creará código que es difícil de mantener. El uso de un estilo personalizado causará problemas de compatibilidad con diferentes temas del nuevo sistema operativo (por ejemplo, lollipop)

Eventualmente, simplemente aplico una animación de rotación a una barra de progreso horizontal. Inspirado por Pete.

  1. Cree la etiqueta en su diseño xml como la barra de progreso horizontal normal.
  2. Asegúrese de que el tamaño y la posición de ProgressBar es lo que desea después de la rotación. (Tal vez establecer un margen negativo ayudará). En mi código giro la vista desde 0,0.
  3. Utilice el siguiente método para girar y establecer un nuevo progreso.

Código:

private void setProgress(final ProgressBar progressBar, int progress) { 
    progressBar.setWillNotDraw(true); 
    progressBar.setProgress(progress); 
    progressBar.setWillNotDraw(false); 
    progressBar.invalidate(); 
} 

private void rotateView(final View v, float degree) { 
    Animation an = new RotateAnimation(0.0f, degree); 
    an.setDuration(0); 
    an.setRepeatCount(0); 
    an.setFillAfter(true);    // keep rotation after animation 
    v.setAnimation(an); 
} 
8

que esto ya que es un antiguo puesto, pero he encontrado una solución muy sencilla a este problema que tal vez puede ayudar a alguien. En primer lugar en absoluto crear un progress_drawable_vertical.xml así:

<?xml version="1.0" encoding="utf-8"?> 
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> 
<item android:id="@android:id/background"> 
    <color android:color="#777" /> 
</item> 
<item android:id="@android:id/progress"> 
    <clip 
     android:clipOrientation="vertical" 
     android:gravity="bottom"> 
     <shape> 
      <gradient 
       android:startColor="#00FF00" 
       android:centerColor="#FFFF00" 
       android:endColor="#FF0000" 
       android:angle="90" /> 
     </shape> 
    </clip> 
</item> 
</layer-list> 

Entonces sólo tiene que utilizar esto en su progressBar:

<ProgressBar 
    android:id="@+id/progress_bar" 
    style="@android:style/Widget.ProgressBar.Horizontal" 
    android:layout_centerInParent="true" 
    android:layout_width="wrap_content" 
    android:layout_height="match_parent" 
    android:max="100" 
    android:progress="33" 
    android:progressDrawable="@drawable/progress_drawable_vertical" /> 

También he creado una progress_drawable_horizontal.xml

<?xml version="1.0" encoding="utf-8"?> 
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> 
<item android:id="@android:id/background"> 
    <color android:color="#777" /> 
</item> 
<item android:id="@android:id/progress"> 
    <clip 
     android:clipOrientation="horizontal" 
     android:gravity="left"> 
     <shape> 
      <gradient 
       android:startColor="#00FF00" 
       android:centerColor="#FFFF00" 
       android:endColor="#FF0000" /> 
     </shape> 
    </clip> 
</item> 
</layer-list> 

con el objetivo de mantener el mismo estilo definido en progress_drawable_vertical.xml

La clave aquí es el uso correcto de android:clipOrientation y android:gravity.

Encontré esta solución here y el núcleo de la solución es similar a jagsaund pero un poco más simple.

+0

Esta solución funcionó para mis necesidades – Brian

0

imagen progrebar simple vista

ejemplo

viewHolder.proBarTrueImage.setMaximalValue(147); 
viewHolder.proBarTrueImage.setLevel(45); 
viewHolder.proBarTrueImage.setColorResource(R.color.corner_blue); 

clase simple

public class ProgressImageView extends ImageView { 

private Context mContext; 
private Paint paint; 
private RectF rectf; 

private int maximalValue = 1; 
private int level = 0; 
private int width; 
private int height; 

public ProgressImageView(Context context) { 
    super(context); 
    init(context, null, 0); 
} 

public ProgressImageView(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    init(context, attrs, 0); 
} 

public ProgressImageView(Context context, AttributeSet attrs, int defStyleAttr) { 
    super(context, attrs, defStyleAttr); 
    init(context, attrs, defStyleAttr); 
} 

private void init(Context context, AttributeSet attrs, int defStyleAttr){ 

    mContext = context; 
    paint = new Paint(); 
    rectf = new RectF(); 
    paint.setColor(Color.GRAY); 
    paint.setStyle(Paint.Style.FILL); 
}; 

@Override 
protected void onDraw(Canvas canvas) { 

    float dif = (float) height/(float) maximalValue; 
    int newHeight = height - (int) (dif * level); 

    rectf.set(0,newHeight, width, height); 
    canvas.drawRect(rectf, paint); 

    super.onDraw(canvas); 
} 

@Override 
protected void onSizeChanged(int w, int h, int oldw, int oldh) { 
    super.onSizeChanged(w, h, oldw, oldh); 
    this.width = w; 
    this.height = h; 
} 

public void setMaximalValue(int maximalValue) { 
    this.maximalValue = maximalValue; 
    invalidate(); 
} 

public void setLevel(int level) { 
    this.level = level; 
    invalidate(); 
} 

public void setColorResource(int color) { 

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 
     color = mContext.getResources().getColor(color,mContext.getTheme()); 
    }else { 
     color = mContext.getResources().getColor(R.color.corner_blue); 
    } 

    setColor(color); 
} 

public void setColor(int color){ 
    if (paint != null){ 
     paint.setColor(color); 
     invalidate(); 
    } 
} 

}

2

he encontrado la mejor solución probablemente (más fácil & más versátil):)

Esta es una publicación anterior, pero fue tan difícil para mí encontrar esta solución tan fácil, así que pensé que debería publicarla ...

Simplemente use un scale-drawable (o un parche de 9 si lo desea), sin necesidad de CUALQUIER OTRO código.

Ejemplo:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> 

    <item android:id="@android:id/background" android:drawable="@color/transparent"/> 

    <item android:id="@android:id/progress"> 
     <scale android:scaleGravity="bottom" android:scaleWidth="0%" android:scaleHeight="100%"> 
      <shape > 
       <solid android:color="@color/blue"/> 
       <corners android:topRightRadius="1dp" android:topLeftRadius="1dp"/> 
      </shape> 
     </scale> 
    </item> 
</layer-list> 

Y por supuesto el código normal:

<ProgressBar 
    android:id="@+id/progress_bar" 
    style="@android:style/Widget.ProgressBar.Horizontal" 
    android:layout_width="24dp" 
    android:layout_height="match_parent" 
    android:max="1000" 
    android:progress="200" 
    android:progressDrawable="@drawable/progress_scale_drawable" /> 

Aviso líneas del scale-drawable 's XML (las líneas mágicas):

android:scaleGravity="bottom" //scale from 0 in y axis (default scales from center Y) 
android:scaleWidth="0%"  //don't scale width (according to 'progress') 
android:scaleHeight="100%"  //do scale the height of the drawable 
+0

la respuesta más fácil y mejor hasta el momento :) gracias amigo – mohnage7

-1
<ProgressBar 
     android:id="@+id/battery_pb" 
     android:rotation="270" 
     android:progress="100" 
... 
/> 

Uso androide: rotación = "270" a 100% sea como abajo a arriba o androide: rotación = "90" a 100% sea como arriba a abajo

+0

¡No funciona simplemente por rotación! –

+0

no funciona en su caso ... –

0

Creación de la barra de progreso (I convierte el código de C# para java así podría no ser 100% correcto)

ProgressBar progBar = new ProgressBar(Context, null, Android.resource.attribute.progressDrawable); 
progBar.progressDrawable = ContextCompat.getDrawable(Context, resource.drawable.vertical_progress_bar); 
progBar.indeterminate = false; 

vertical_progress_bar.xml

<?xml version="1.0" encoding="utf-8"?> 
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android" > 

     <item android:id="@android:id/background"> 
     <shape> 
      <solid android:color="@color/grey" /> 

      <corners android:radius="20dip" /> 
     </shape> 
     </item> 
     <item android:id="@android:id/progress"> 
     <scale 
      android:drawable="@drawable/vertical_progress_bar_blue_progress" 
      android:scaleHeight="100%" 
      android:scaleGravity="bottom"/> 
     </item> 
    </layer-list> 

vertical_progress_bar_blue_progress.xml

<?xml version="1.0" encoding="utf-8"?> 
<shape xmlns:android="http://schemas.android.com/apk/res/android" > 

    <corners 
     android:radius="20dip" /> 

    <solid android:color="@color/ProgressBarFourth" /> 

</shape> 

¿Qué va a hacer que su barra vertical es el scaleHeight y scaleGravity atributos en vertical_progress_bar.xml.

Se termina buscando algo como esto:

enter image description here

0
This perfectly works 

<?xml version="1.0" encoding="utf-8"?> 
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:id="@android:id/background"> 
     <shape> 
      <gradient 
       android:startColor="#DDDDDD" 
       android:centerColor="#DDDDDD" 
       android:centerY="0.75" 
       android:endColor="#DDDDDD" 
       android:angle="270" 
       /> 
     </shape> 
    </item> 

    <item 
     android:id="@android:id/progress"> 
     <clip 
      android:clipOrientation="vertical" 
      android:gravity="top"> 
      <shape> 
       <gradient 
        android:angle="0" 
        android:startColor="#302367" 
        android:centerColor="#7A5667" 
        android:endColor="#C86D67"/> 
      </shape> 
     </clip> 
    </item> 
</layer-list> 

    <ProgressBar 
      android:id="@+id/progress_bar" 
      style="?android:attr/progressBarStyleHorizontal" 
      android:layout_width="5dp" 
      android:layout_height="match_parent"`enter code here` 
      android:progressDrawable="@drawable/progress_dialog"/> 
Cuestiones relacionadas