2010-01-16 19 views
9

Estoy tratando de crear una barra de progreso personalizada en Android. He utilizado el siguiente archivo XML para ello (progress_bar_horizontal.xml):Barra de progreso redondeada en ambos lados en Android

<?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="8dip" /> 
    <stroke android:width="2dip" android:color="#FFFF"/> 
    <solid android:color="#FFFF"/>    
    </shape> 
    </item> 
    <item android:id="@android:id/secondaryProgress"> 
    <clip> 
    <shape> 
    <corners android:radius="8dip" /> 
    <stroke android:width="2dip" android:color="#FFFF"/> 
    <solid android:color="#FF00"/> 
    </shape> 
    </clip> 
    </item> 
    <item android:id="@android:id/progress"> 
    <clip> 
    <shape> 
    <corners android:radius="8dip" /> 
    <stroke android:width="2dip" android:color="#FFFF"/> 
    <solid android:color="#FF00"/> 
    </shape> 
    </clip> 
    </item> 
</layer-list> 

Todo funciona muy bien, aparte del hecho me gustaría tener el progreso en mi barra de progreso redondeado en ambos lados. El código mencionado hace que una barra de progreso se redondee en el lado izquierdo y simplemente se corte (no se redondee) en el lado derecho. Es debido a la etiqueta del clip, probablemente. ¿Podrías por favor ayudarme con eso? ¿Qué debería cambiar para tener el progreso en mi barra de progreso redondeado en ambos lados?

El diseño completo va a continuación:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:orientation="vertical"> 
    <LinearLayout 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:orientation="vertical" 
    android:background="@drawable/gradient_progress" 
    android:padding="10dip" 
    > 
    <LinearLayout 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:orientation="horizontal" 
    > 
    <TextView 
    android:id="@+id/progress_header" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:textColor="#FF000000" 
    android:textAppearance="?android:attr/textAppearanceMedium" 
    android:textStyle="bold" 
    android:text="Uploading"    
    /> 
    <TextView 
    android:id="@+id/progress_percent" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:textColor="#FF000000" 
    android:textAppearance="?android:attr/textAppearanceMedium" 
    android:textStyle="bold" 
    android:text="55%"   
    android:paddingLeft="10dip" 
    />  
    </LinearLayout>   
    <ProgressBar 
    android:id="@+id/progress_bar" 
    style="?android:attr/progressBarStyleHorizontal" 
    android:layout_gravity="center" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:progressDrawable="@drawable/progress_bar_horizontal" 
    android:maxHeight="12dip"  
    android:minHeight="12dip"  
    android:max="100" 
    /> 
    </LinearLayout> 
</LinearLayout> 

Este es el resultado de mi esfuerzo: link text

Me gustaría que la barra roja que tenga bordes redondeados en el lado derecho también. Muchas gracias por sus comentarios.

+0

podemos ver el diseño donde poner este th ing dentro? También asumo que vio progress_horizontal.xml en SDK. –

+0

Gracias por la entrada. Sí, he visto las muestras del marco pero desafortunadamente no manejan mi caso. He actualizado la pregunta con el diseño completo y he cargado la imagen que muestra la barra actual. Gracias por tu consideración. – youri

Respuesta

23

Aquí es una respuesta actualizada a los tiempos:

El código fuente de Android utiliza Patch 9 archivos para lograr el efecto: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4_r1/frameworks/base/core/res/res/drawable/progress_horizontal_holo_dark.xml/

Así que empieza en su xml diseño:

<ProgressBar 
    android:id="@+id/custom_progress_bar" 
    style="@android:style/Widget.ProgressBar.Horizontal" 
    android:indeterminateOnly="false" 
    android:progressDrawable="@drawable/custom_progress_bar_horizontal" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:minHeight="13" 
    android:progress="33" 
    android:secondaryProgress="66" /> 

Usted puede mover mucho de esto a un estilo xml, pero eso está al lado del punto. Lo que realmente importa es android:progressDrawable="@drawable/custom_progress_bar_horizontal" - lo que nos va a permitir especificar nuestras propias barras de progreso personalizada:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:id="@android:id/background" 
      android:drawable="@android:drawable/custom_progress_bg" /> 
    <item android:id="@android:id/secondaryProgress"> 
     <scale android:scaleWidth="100%" 
       android:drawable="@android:drawable/custom_progress_secondary" /> 
    </item> 
    <item android:id="@android:id/progress"> 
     <scale android:scaleWidth="100%" 
       android:drawable="@android:drawable/custom_progress_primary" /> 
    </item> 
</layer-list> 

O usted no tiene que usar un parche para su 9 del fondo, por ejemplo, he aquí una sencilla blanco fondo con un borde 1DP:

<item android:id="@android:id/background"> 
    <shape> 
     <corners android:radius="6.5dp" /> 

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

     <stroke 
      android:width="1dp" 
      android:color="@android:color/darker_gray" /> 
    </shape> 
</item> 

Android activos Studio cuenta con una herramienta impresionante para ayudarle a generar archivos de parches 9: http://android-ui-utils.googlecode.com/hg/asset-studio/dist/nine-patches.html

Ejemplo xdpi primaria PNG con relleno antes de la herramienta: Primary progress bar
Ejemplo xdpi secundaria png con el relleno antes de la herramienta: Secondary progress bar

Y el resultado final: Custom progress bar

+0

me estoy poniendo problema-- al principio, parece que está "exprimido" así que me puedes dar el ejemplo –

+0

el truco de escala con el trazado no-9-drawable (la forma uno) es exactamente lo que estaba buscando y un muy buen truco :) –

2

Por lo que yo sé, esto no es posible. Porque internamente ClipDrawable (es decir, etiqueta de clip) corta la forma dada/dibujable usando canvas.clipRect(). Por cierto, puede copiar la fuente ClipDrawable de here y recortar una ruta particular en función del nivel de progreso.

+0

¿Qué tal agregar un nuevo elemento a la lista de capas, que agregaría un extremo redondo a la barra de progreso recortada? Me gusta: 5dp; ... Tendría problemas cuando la barra era 100% o casi, pero de todos modos ¿hay alguna posibilidad de esta manera? ¿O ya lo has pensado? – neteinstein

+0

Agregar un elemento en la lista de capas no ayudará, porque tendrá la misma altura y ancho que todas las otras capas. También necesita cambiar ProgressBar para manejar la nueva capa. – Karan

+0

bien, gracias por la respuesta rápida! – neteinstein

0

Con el fin de resolver el problema por el que los gráficos de gama superponen a sí mismos cuando el progreso es muy baja, He escrito una extensión para la clase ProgressBar que agrega un desplazamiento de inicio fijo a la barra de progreso, mientras que de otro modo funciona normalmente.

Simplemente llame a 'setMaxWithPercentOffset()' o 'setMaxWithOffset()' en lugar de 'setMax()' pasando el valor que desea agregar como un desplazamiento inicial a la barra de progreso.

Si alguien ha resuelto este problema sin requerir el inicio de la compensación, ¡hágamelo saber!

/** 
* This progress bar can be used when the progress bar end graphics are styled in some way. 
* In this case, the progress bar must always have a small percentage of progress, otherwise 
* the styled ends of the progress overlap each other. 
* 
*/ 
public class EndStyledProgressBar extends ProgressBar { 
    private static final int DEFAULT_START_OFFSET_PERCENT = 5; 

    private int mStartOffset; 
    private int mRealMax; 

    public EndStyledProgressBar(Context context) { 
     super(context); 
     commonConstructor(); 
    } 

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

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

    private void commonConstructor() { 
     mRealMax = super.getMax(); 
     mStartOffset = 0; 

     setMaxWithPercentOffset(DEFAULT_START_OFFSET_PERCENT, mRealMax); 

     super.setProgress(super.getProgress() + mStartOffset); 
     super.setSecondaryProgress(super.getSecondaryProgress() + mStartOffset); 
    } 

    public void setProgress(int progress) { 
     super.setProgress(progress + mStartOffset); 
    } 

    public void setSecondaryProgress(int secondaryProgress) { 
     super.setSecondaryProgress(secondaryProgress + mStartOffset); 
    } 

    public int getProgress() { 
     int realProgress = super.getProgress(); 
     return isIndeterminate() ? 0 : (realProgress - mStartOffset); 
    } 


    public int getSecondaryProgress() { 
     int realSecondaryProgress = super.getSecondaryProgress(); 
     return isIndeterminate() ? 0 : (realSecondaryProgress - mStartOffset); 
    } 

    public int getMax() { 
     return mRealMax; 
    } 


    /** 
    * Don't call this, instead call setMaxWithPercentOffset() or setStartOffsetInPercent() 
    * 
    * @param max 
    */ 
    public void setMax(int max) { 
     super.setMax(max); 
    } 

    /** 
    * Sets a new max with a start offset (in percent) included. 
    * 
    * @param startOffsetInPercent start offset for the progress bar to avoid graphic errors. 
    */ 
    public void setMaxWithPercentOffset(int startOffsetInPercent, int max) { 
     mRealMax = max; 
     int startOffset = (mRealMax * startOffsetInPercent)/100; 

     setMaxWithOffset(startOffset, max); 
    } 

    /** 
    * Sets a new max with a start offset included. 
    * 
    * @param startOffset start offset for the progress bar to avoid graphic errors. 
    */ 
    public void setMaxWithOffset(int startOffset, int max) { 
     mRealMax = max; 

     super.setMax(startOffset + max); 

     setStartOffset(startOffset); 

     super.setMax(startOffset + max); 
    } 


    /** 
    * Sets a new start offset different from the default of 5% 
    * 
    * @param startOffset start offset for the progress bar to avoid graphic errors. 
    */ 
    private void setStartOffset(int startOffset) { 
     int newStartOffset = startOffset; 

     // Ensure the start offset is not outside the range of the progress bar 
     if (newStartOffset < 0) newStartOffset = 0; 
     if (newStartOffset >= super.getMax()) newStartOffset = super.getMax(); 

     // Apply the start offset difference 
     if (mStartOffset != newStartOffset) { 
      int diff = newStartOffset - mStartOffset; 
      super.setMax(super.getMax() + diff); 
      super.setProgress(super.getProgress() + diff); 
      super.setSecondaryProgress(super.getSecondaryProgress() + diff); 
      mStartOffset = newStartOffset; 
     } 
    } 
} 
6

acaba de cambiar la etiqueta <clip> a <scale> como esto:

<scale android:scaleWidth="100%"> 
+0

No estoy seguro de por qué esto no está recibiendo más atención. Funciona maravillosamente. ¡Gracias! –

0

finales redondeadas ambos lados Barra de progreso sin 9-patch es: android:progressDrawable="@drawable/progress_horizontal_green"

<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> 
<item android:id="@android:id/progress"> 
    <scale android:scaleWidth="100%"> 
     <shape> 
      <corners android:radius="5dip"/> 
      <solid android:color="#33FF33"/> 
     </shape> 
    </scale> 
</item> 

Cuestiones relacionadas