2010-01-16 17 views
9

Sto cercando di creare una barra di avanzamento personalizzata in Android. Ho usato il seguente file XML per esso (progress_bar_horizontal.xml):Barra di avanzamento arrotondata su entrambi i lati in 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> 

Tutto grandi opere a parte il fatto che mi piacerebbe avere i progressi nella mia barra di avanzamento arrotondato su entrambi i lati. Il codice di cui sopra fa una barra di progresso da arrotondare sul lato sinistro e semplicemente tagliare (non arrotondato) sul lato destro. Probabilmente è a causa del tag clip. Potresti per favore aiutarmi su questo? Cosa dovrei cambiare per avere i progressi nella mia barra di progresso arrotondati su entrambi i lati?

Il layout completo va sotto:

<?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> 

Ecco il risultato del mio impegno: link text

vorrei che la barra rossa di avere bordi arrotondati sul lato destro della strada pure. Grazie mille per i vostri commenti.

+0

possiamo vedi il layout dove stai mettendo questo th in? Suppongo anche che tu abbia visto progress_horizontal.xml in SDK. –

+0

Grazie per l'input. Sì, ho visto i campioni del framework ma sfortunatamente non gestiscono il mio caso. Ho aggiornato la domanda con il layout completo e ho caricato l'immagine che mostra la barra corrente. Grazie per la tua considerazione. – youri

risposta

23

Ecco una risposta aggiornata per i tempi:

Il codice sorgente di Android utilizza Patch 9 file per ottenere l'effetto: 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/

Così inizia nel layout xml:

<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" /> 

È può spostare molto di questo in uno stile xml ma questo è oltre il punto. Ciò di cui abbiamo veramente a cuore è android:progressDrawable="@drawable/custom_progress_bar_horizontal" - che sta per permetterci di specificare le nostre barre di avanzamento personalizzato:

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

Oppure non c'è bisogno di usare un Patch 9 per il vostro background-per esempio qui è un semplice bianco sfondo con un bordo 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 Asset Studio ha uno strumento fantastico per aiutarvi a generare Patch 9 file: http://android-ui-utils.googlecode.com/hg/asset-studio/dist/nine-patches.html

Esempio xdpi primaria png con imbottitura prima che lo strumento: Primary progress bar
Esempio xdpi secondario png con imbottitura prima che lo strumento: Secondary progress bar

E l'output finale: Custom progress bar

+0

sto andando sul punto-- punto all'inizio, sembra che sia "spremuto" così puoi fornirmi l'esempio –

+0

il trucco di scala con il non-9-path drawable (la forma uno) è esattamente quello che stavo cercando e un trucco MOLTO bello :) –

2

Per quanto ne so, questo non è possibile. Perché internamente lo ClipDrawable (ovvero il tag della clip) taglia la forma o il disegnabile dato usando canvas.clipRect(). A proposito, è possibile copiare la sorgente ClipDrawable da here e ritagliare un percorso particolare in base al livello di avanzamento.

+0

Che ne dici di aggiungere un nuovo elemento all'elenco dei livelli, che aggiungerebbe un arrotondamento alla barra di avanzamento ritagliata. Mi piace: 5dp; ... Avrebbe problemi quando la barra era al 100% o quasi, ma comunque c'è qualche possibilità in questo modo? O ci hai già pensato? – neteinstein

+0

L'aggiunta di un elemento nell'elenco dei livelli non aiuta, poiché avrà la stessa altezza e larghezza di tutti gli altri livelli. Inoltre è necessario modificare ProgressBar per gestire il nuovo livello. – Karan

+0

ok, grazie per la risposta veloce! – neteinstein

0

Per risolvere il problema in cui la grafica di estremità si sovrappongono quando il progresso è molto bassa, Ho scritto un'estensione della classe ProgressBar che aggiunge un offset iniziale fisso alla barra di avanzamento, mentre altrimenti funziona normalmente.

Basta chiamare 'setMaxWithPercentOffset()' o 'setMaxWithOffset()' anziché 'setMax()' passando il valore che si desidera aggiungere come offset iniziale alla barra di avanzamento.

Se qualcuno ha risolto questo problema senza richiedere l'offset di partenza fammi sapere!

/** 
* 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

solo cambiare l'etichetta <clip> a <scale> simili:

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

Non sono sicuro del motivo per cui questo non sta ottenendo più attenzione. Funziona magnificamente. Grazie! –

0

finale arrotondati entrambi i lati progrediscono bar senza 9-patch è: 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> 

Problemi correlati