2013-02-22 4 views
11

Ho un modulo che sto generando dinamicamente dai dati che ricevo da un servizio web. Questo servizio Web fornisce immagini che devono essere utilizzate nella creazione di elementi di input. Sto avendo difficoltà a impostare il progressDrawable di un RatingBar. Anche se XML sono in grado di applicare un'immagine personalizzata utilizzando il seguente come progressDrawable:Costruzione di un RatingBar utilizzando le immagini caricate dal web

<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:id="@+android:id/background" android:drawable="@drawable/custom_star" /> 
    <item android:id="@+android:id/secondaryProgress" android:drawable="@drawable/custom_star" /> 
    <item android:id="@+android:id/progress" android:drawable="@drawable/custom_star" /> 
</layer-list> 

dove custom_star è un'immagine .png semplice, e con @android:style/Widget.RatingBar come lo stile RatingBar. Questo funziona bene:

Working start

ma sto voler cambiare custom_star dinamicamente.

In codice, ho provato a regolare il drawable progressi usando una bitmap direttamente:

Drawable d = new BitmapDrawable(getResources(), downloadedImage); 
ratingBar.setProgressDrawable(d); 

e anche con la costruzione di un layer-list:

LayerDrawable layerDrawable = new LayerDrawable(new Drawable[] { 
    getResources().getDrawable(R.drawable.custom_star), 
    getResources().getDrawable(R.drawable.custom_star),    
    getResources().getDrawable(R.drawable.custom_star) 
}); 

layerDrawable.setId(0, android.R.id.background); 
layerDrawable.setId(1, android.R.id.secondaryProgress); 
layerDrawable.setId(2, android.R.id.progress); 

ratingBar.setProgressDrawable(layerDrawable); 

Né funziona per me; sia comportare la custom_star drawable che appare una volta, si estendeva dalle dimensioni del RatingBar:

enter image description here

Tutte le idee?

Update: risposta

di Luksprog seguito ha fatto un miglioramento, ma sto ancora avere un paio di questioni. Ora, il drawable stella non è allungato e il valore può essere impostato tramite il tocco, ma sembra come così con 3/5 selezionato:

no secondary

e 5/5 selezionati:

too many stars

Credo che il ridimensionamento delle immagini possa essere corretto con poche modifiche, ma non sembra che il drawable secondaryProgress non sia impostato, il drawable utilizzato per le stelle non selezionate in grigio. Senza quello, non è molto utilizzabile.

risposta

11

Qualche idea?

Quando si utilizza il default progressDrawable o un set progressDrawable attraverso un tema tutto sarà ok come nel costruttore per il RatingBar (la sua superclasse ProgressBar per essere più precisi) widget di un metodo sarà chiamato a "fare tessere" da che disegnabile. Quando si utilizza il metodo setProgressDrawable questo non accade e se si passa un semplice BitmapDrawable o un LayerDrawable (con semplice BitmapDrawables) il numero Drawable verrà semplicemente allungato per coprire l'area di sfondo del widget (ciò che si vede).

Per farlo funzionare, è necessario eseguire manualmente ciò che fa RatingBar all'inizio, creare le tessere insieme allo ClipDrawables che utilizza.Ho scritto un metodo per questo, seguendo il codice sorgente del widget ProgressBar:

private Drawable buildRatingBarDrawables(Bitmap[] images) { 
    final int[] requiredIds = { android.R.id.background, 
      android.R.id.secondaryProgress, android.R.id.progress }; 
    final float[] roundedCorners = new float[] { 5, 5, 5, 5, 5, 5, 5, 5 }; 
    Drawable[] pieces = new Drawable[3]; 
    for (int i = 0; i < 3; i++) { 
     ShapeDrawable sd = new ShapeDrawable(new RoundRectShape(
       roundedCorners, null, null)); 
     BitmapShader bitmapShader = new BitmapShader(images[i], 
       Shader.TileMode.REPEAT, Shader.TileMode.CLAMP); 
     sd.getPaint().setShader(bitmapShader); 
     ClipDrawable cd = new ClipDrawable(sd, Gravity.LEFT, 
       ClipDrawable.HORIZONTAL); 
     if (i == 0) { 
      pieces[i] = sd; 
     } else { 
      pieces[i] = cd; 
     } 
    } 
    LayerDrawable ld = new LayerDrawable(pieces); 
    for (int i = 0; i < 3; i++) { 
     ld.setId(i, requiredIds[i]); 
    } 
    return ld; 
} 

allora si dovrebbe utilizzare il LayerDrawable restituito da questo metodo con il metodo setProgressDrawable. Lo RatingBar imposta la sua larghezza moltiplicando la larghezza di uno dei bitmap di stato con il numero di stelle, quindi per mostrare la giusta quantità di stelle questo deve essere calcolato anche.

+0

Grandi cose. Questo è sicuramente funzionante per me, anche se non riesco a ottenerlo per impostare secondaryProgress. Le stelle appaiono quando si fa clic, ma quelle in background non selezionate in grigio non appaiono (sto usando un diverso drawable, R.drawable.star_off). – blork

+1

Mentre la tua soluzione esatta non ha funzionato per me, ho controllato il [codice sorgente Android per ProgressBar] (http://grepcode.com/file_/repository.grepcode.com/java/ext/com.google.android/ android/2.3.3_r1/android/widget/ProgressBar.java /) come hai suggerito, e lo strappo del metodo tileify() ha funzionato benissimo per me. Grazie! – blork

+2

@blork Mi dispiace per il codice che ho postato (non ho avuto molto tempo), non ha replicato completamente quel metodo (in qualche modo ho perso il flag 'clip'). Sono sicuro che sei riuscito anche a far sì che le stelle abbiano le dimensioni corrette. Il 'RatingBar' imposta la sua larghezza moltiplicando la larghezza di una delle bitmap con il numero di stelle (calcolando questo nel metodo' onMeasure' di un 'RatingBar' personalizzato dovrebbe mostrare la giusta quantità di stelle). – Luksprog

0

gli ID sono sbagliati, è necessario impostare @android: id/sfondo @android: id/secondaryProgress @android: id/progresso

È inoltre possibile definire un disegnabile in XML contenente la personalizzazione

<?xml version="1.0" encoding="utf-8"?> 
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:id="@+android:id/background" 
      android:drawable="@drawable/star_empty" /> 
    <item android:id="@+android:id/secondaryProgress" 
      android:drawable="@drawable/star_empty" /> 
    <item android:id="@+android:id/progress" 
      android:drawable="@drawable/star_full" /> 
</layer-list> 

Ed è possibile utilizzare setMax sull'oggetto RatingBar per impostare la quantità massima di stelle che possono essere visualizzati

0

E 'molto più facile con tale modo lution:

RatingBar ratingBar = new RatingBar(new ContextThemeWrapper(context, R.style.AppTheme_RatingBar), null, 0);