2014-11-26 9 views
6

Ich muss eine Repaint der RatingBar Kontrolle erzwingen.Android RatingBar Malerei selbst falsch

Nach vielen Problemen mit der Bewertungsleiste und den Stilen, habe ich fast alles zum Laufen gebracht.

Ich benutze es in einem Listenansicht Element. Aufgrund dessen, wie es funktioniert, muss man ein wenig mit seinem Aussehen und Verhalten "kämpfen". Ich habe am Ende eine Lösung verwendet, die ich in SO gefunden habe, wo man sie als Indikator verwendet, aber wo man manuell berechnet, welche Punktzahl der Klick auf die Bewertungsleiste entspricht. Der Code immer ergibt das richtige Ergebnis, wenn durch den Code, aber die Kontrolle Malerei von sich selbst ist falsch das erste Mal. Hier ist mein Code in getView „Teil eins“:

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;  
    }     
    }); 

Das Problem is.When die Bewertungs zunächst gezeigt wird, das erste Mal beim Klicken überall auf sie wird es selbst machen ziehen, als ob man immer gewählt die maximale Punktzahl. Wenn man jedoch das Steuerelement ausblendet und es erneut anzeigt, zeichnet es alles korrekt. Dies ist jedoch eine "natürliche Benutzerinteraktionsverzögerung" - z. durch Klicken auf eine Schaltfläche, die den Sichtbarkeitsstatus wechselt. Wenn ich versuche, ein Repaint in Code mit Invalidate- oder Setvisibility-Anweisungen zu erzwingen, passiert nichts.

Dies ist der Code "Teil 2", wo ich die Bewertungsleiste in getView initialisieren, wenn es angezeigt wird:

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

Und das ist seine 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> 

Als Referenz sind diese einige der stackoverflows die mich bekam so weit ich bin:

(aber leider nicht löse mein spezifisches Problem.)

Ich habe viele verschiedene Kombinationen ausprobiert, und in meinem Fall ist der hier angegebene Code das, was dem gewünschten Verhalten und Aussehen am nächsten kommt. Nur mit dem Problem wird der Punktestand bei "First Show" falsch gezeichnet.

Ich habe versucht, z.B. invalidate, aber ich glaube, dass seine internen Flags ignorieren, er die Anforderung ungültig machen.

Antwort

6

Ich denke, das Problem liegt in der Größenordnung von diesen Aussagen:

// 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); 

Also, versuchen Sie diese Reihenfolge:

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

Was // force repaint and set visible - how?, sollte dies nicht erforderlich. setRating(float) sollte ein Update erzwingen. Entfernen Sie einfach rating.setVisibility(View.INVISIBLE); von ACTION_UP Teil Ihres Codes. Wenn die RatingBar immer noch nicht aktualisiert wird, versuchen Sie rating.requestLayout(). Aber, bitte lesen Sie weiter für eine sauberere Lösung.

Sie sagten, dass int starsint = (int) starsf + param_final__data.score_min; den richtigen Wert erhält. Und ich vermute, dass param_final__data.score_cur = starsbyte; Ihre ListView-Daten aktualisiert. Rufen Sie dann einfach notifyDataSetChanged() an und lassen Sie den Adapter die Ansicht mit dem korrekten Wert aktualisieren? Die Änderung in der Reihenfolge der Anweisungen wird jedoch erforderlich sein.

+0

Es scheint, dass Ihre Antwort mein Problem vollständig gelöst hat. Danke, lott - Sie werden nicht glauben, wie viel Zeit ich damit verbracht habe zu versuchen, das zu lösen! Es hat mich wiederholt einige Male und auch viele Versuche, das Neuzeichnen zu erzwingen. Wie auch immer, ich überprüfe und vergebe das Bounty wenn möglich :) – Tom

+1

@Tom Gern geschehen. Es ist seltsam, dass die Reihenfolge hier wichtig ist. Immer seltsamer, dass es nicht dokumentiert ist. Ich ging durch den Quellcode und fand, dass 'setStepSize (float)' den 'max' Wert ändert, aber 'setNumStars (int)' nicht. Also, ich vermutete, dass, obwohl die Anzahl der gezeichneten Sterne richtig war, der zugrunde liegende 'max' Wert dazu führte, dass' setRating() 'einen ungültigen Fortschritt zeichnete. Wie auch immer, viel Glück beim Testen. Hoffe es geht alles. – Vikram

+0

Ich weiß nicht warum, aber es funktioniert! Vielen Dank! – anil