2014-11-26 30 views
6

Devo forzare un ridisegno del controllo RatingBar.RatingBar Android che si macchia in modo errato

Dopo molti problemi con la barra di valutazione e gli stili, sono riuscito a far funzionare quasi tutto.

Lo uso in un oggetto listview. A causa di come funziona, bisogna "combattere" un po 'con il suo aspetto e il suo comportamento. Ho finito per usare una soluzione che ho trovato su SO, dove si imposta come un indicatore, ma dove si calcola manualmente il punteggio a cui corrisponde il clic sulla barra di valutazione. Il codice sempre restituisce il risultato corretto quando si esegue il ripulitura tramite il codice, ma il controllo di pittura di per sé non è corretto la prima volta. Ecco il mio codice GetView "parte prima":

final RatingBar rating = (RatingBar)view.findViewById(R.id.listitem_catalog_rating); 

    rating.setOnTouchListener(new OnTouchListener() { 
    @Override 

    public boolean onTouch(View v, MotionEvent event) { 
     if (event.getAction() == MotionEvent.ACTION_UP) { 
      float touchPositionX = event.getX(); 
      float width = rating.getWidth(); 
      float starsf = (touchPositionX/width); 
      starsf = starsf * param_final__data.score_max; // 5 
      int starsint = (int) starsf + param_final__data.score_min;         
      byte starsbyte = (byte) starsint; 
      param_final__data.score_cur = starsbyte; 
      starsf = starsint; 
      rating.setRating(starsf); 
      rating.setVisibility(View.INVISIBLE); 
      // force repaint and set visible - how? 
     } 
     else 
     if (event.getAction() == MotionEvent.ACTION_DOWN) { 
      param_final__view.setPressed(true); 
     } 
     else 
     if (event.getAction() == MotionEvent.ACTION_CANCEL) { 
      param_final__view.setPressed(false); 
     } 
     return true;  
    }     
    }); 

Il problema is.When la ratingbar è inizialmente mostrato, la prima volta quando si fa clic su un punto qualsiasi renderà disegnare se stesso come se uno sempre scelto il punteggio massimo. Tuttavia, se uno nasconde il controllo e lo mostra di nuovo, disegna tutto correttamente. Tuttavia, questo è con "naturale ritardo di interazione dell'utente" - ad es. facendo clic su un pulsante che cambia lo stato di visibilità. Se provo a forzare un repaint nel codice usando istruzioni invalidate o setvisibility, non succede nulla.

Questo è il codice "parte 2" dove ho inizializzare il ratingbar in GetView quando viene mostrato:

   rating.setIsIndicator(true); 
       rating.setVisibility(View.VISIBLE); 
       rating.setStepSize(1); 
       //rating.setMax(data.score_max); 
       rating.setNumStars(data.score_max); 
       rating.setRating(data.score_cur); 

E questa è la sua XML:

<RatingBar 
     android:id="@+id/listitem_catalog_rating"   
     android:layout_height="wrap_content" 
     android:layout_width="wrap_content"   
     android:numStars="1" 
     android:stepSize="1.0" 
     android:rating="1.0" 
     style="@style/MicRatingBar"   
     android:visibility="gone" 
     android:layout_marginTop="10dip"    
     android:layout_marginBottom="10dip" 
     /> 

...

<style name="MicRatingBar" parent="@android:style/Widget.RatingBar"> 
    <item name="android:progressDrawable">@drawable/micratingstars</item> 
    <item name="android:minHeight">34dip</item> 
    <item name="android:maxHeight">34dip</item>    
</style> 

...

<?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_background" /> 
    <item android:id="@+android:id/secondaryProgress" android:drawable="@drawable/star_secondaryprogress" /> 
    <item android:id="@+android:id/progress" android:drawable="@drawable/star_progress" /> </layer-list> 

Per riferimento, queste sono alcune delle stackoverflows, che mi ha preso per quanto ne sono:

(ma purtroppo non lo fa risolvere il mio problema specifico.)

Ho provato molte combinazioni diverse e nel mio caso, il codice postato qui è quello che si avvicina di più al comportamento desiderato e al look. Solo con il problema il punteggio viene disegnato in modo errato sul "primo spettacolo".

Ho provato a utilizzare per es. invalida, ma credo che i suoi flag interni facciano ignorare che invalida la richiesta.

risposta

6

Credo che il problema risiede nel l'ordine di queste affermazioni:

// Fine 
rating.setIsIndicator(true); 

// Fine 
rating.setVisibility(View.VISIBLE); 

// Problem - Although not documented, I think this should be 
// called after `setNumStars(int)` 
rating.setStepSize(1); 

// Switch with the statement above 
rating.setNumStars(data.score_max); 

// Fine 
rating.setRating(data.score_cur); 

Quindi, provate questo ordine:

rating.setIsIndicator(true); 
rating.setVisibility(View.VISIBLE); 
rating.setNumStars(data.score_max); 
rating.setStepSize(1); 
rating.setRating(data.score_cur); 

Per quanto riguarda // force repaint and set visible - how?, questo dovrebbe non essere necessaria. setRating(float) dovrebbe forzare un aggiornamento. Basta rimuovere rating.setVisibility(View.INVISIBLE); da ACTION_UP parte del tuo codice. Se RatingBar continua a non aggiornarsi, prova a rating.requestLayout(). Ma, leggi ulteriori informazioni per una soluzione più pulita.

Hai detto che int starsint = (int) starsf + param_final__data.score_min; sta ottenendo il valore corretto. E immagino che lo param_final__data.score_cur = starsbyte; aggiorni i dati di ListView. Allora perché non chiamare semplicemente notifyDataSetChanged() e lasciare che l'adattatore aggiorni la vista con il valore corretto? Tuttavia, il cambiamento nell'ordine delle dichiarazioni sarà richiesto.

+0

Sembra che la tua risposta abbia risolto completamente il mio problema. Grazie a lottare - non crederai a quanto tempo ho impiegato per cercare di risolvere questo problema! Mi fa rifare gli stili, ecc., Un paio di volte e anche molti esperimenti che cercano di forzare il ridisegno. Ad ogni modo, controllerò e assegnerò la taglia quando possibile :) – Tom

+1

@Tom Prego. È strano che l'ordine sia importante qui. Sempre più strano che non sia documentato. Ho passato il codice sorgente e ho scoperto che 'setStepSize (float)' cambia il valore 'max', ma' setNumStars (int) 'no. Quindi, sospettavo che anche se il numero di stelle disegnate fosse corretto, il valore 'max' sottostante causava' setRating() 'per disegnare progressi non validi. Comunque, buona fortuna con i test. Spero che tutto funzioni. – Vikram

+0

Non so perché, ma funziona! Grazie mille! – anil