2015-08-10 7 views
16

Ich möchte eine alternierende Farbe für meine benutzerdefinierte ListView Klasse festlegen.Alternative Hintergrundfarbe für die ListView-Klasse auch ohne Daten

Der Code ist unten angegeben:

import android.content.Context; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.graphics.Rect; 
import android.util.AttributeSet; 
import android.view.View; 
import android.widget.ListView; 

    public class CustomListView extends ListView { 
    private Paint mPaint    = new Paint(); 
    private Paint mPaintBackground = new Paint(); 

    public CustomListView(Context context, AttributeSet attrs) { 
     super(context, attrs); 

     mPaint.setColor(Color.parseColor("#1A000000")); 

    } 

    @Override 
    protected void dispatchDraw(Canvas canvas) { 
     super.dispatchDraw(canvas); 
     final int currentHeight = getMeasuredHeight(); 

     final View lastChild = getChildAt(getChildCount() - 1); 
     if (lastChild == null) 
      return; 
     for (int i = 0; i < getChildCount(); i++) { 
      if (getChildCount() % 2 == 0) { 
       mPaintBackground.setColor(Color.WHITE); 
      } else { 
       mPaintBackground.setColor(Color.RED); 
      } 
     } 

     final int lastChildBottom = lastChild.getBottom(); 

     final int lastChildHeight = lastChild.getMeasuredHeight(); 

     final int nrOfLines = (currentHeight - lastChildBottom)/lastChildHeight; 

     Rect r = new Rect(0, lastChildBottom, getMeasuredWidth(), getMeasuredHeight()); 
     canvas.drawRect(r, mPaintBackground); 
     canvas.drawLine(0, lastChildBottom, getMeasuredWidth(), lastChildBottom, mPaint); 
     for (int i = 0; i < nrOfLines; i++) { 
      canvas.drawLine(0, lastChildBottom + (i + 1) * lastChildHeight, getMeasuredWidth(), lastChildBottom + (i + 1) * lastChildHeight, mPaint); 
     } 
     return; 
    } 
    } 

Um eine wechselnde Hintergrundfarbe für ListView zu bekommen, habe ich diesen Code verwendet:

for (int i = 0; i < getChildCount(); i++) { 
    if (getChildCount() % 2 == 0) { 
     mPaintBackground.setColor(Color.WHITE); 
    } else { 
     mPaintBackground.setColor(Color.RED); 
    } 
} 

Innerhalb des Adapters:

if (position % 2 == 0) { 
     view.setBackgroundColor(Color.RED); 
    } else { 
     view.setBackgroundColor(Color.WHITE); 
    } 

Aber es zeigt immer eine Farbe, rot oder weiß mit allem, was ich versuche. Ich bekomme keine wechselnden Farben weiß-rot-weiß-rot.

+0

Sie verwenden eine falsche Methode, um Ihr Ergebnis zu erzielen. Die Methode dispatchDraw wird nur einmal aufgerufen. Sie sollten die getView-Methode für ein solches Verhalten verwenden, das für jedes Element aufgerufen wird. @faizan hat die richtige Lösung vorgeschlagen – SAIR

+0

Oh. Ja wirklich ? So wie es wäre? – Piyush

+0

sehen Sie den kompletten Kommentar. – SAIR

Antwort

12

Der Grund dafür ist, dass sich Ihre for-Schleife nie ändert. Sie überprüfen immer getChildCount() % 2. getChildCount() gibt für jede Iteration dasselbe zurück. Sie benötigen eine Überprüfung zu tun, basierend auf der Position:

for(int i = 0; i < getChildCount(); i++){ 
    if(i % 2 == 0){ 
     mPaintBackground.setcolor(Color.WHITE); 
    } else{ 
     mPaintBackground.setColor(Color.RED); 
    } 
} 

Wenn es hilft, benennen Sie Ihre Zählvariable i-position so dass dies für Sie in Zukunft besser lesbar sein wird, oder eine Notiz davon zu helfen dich selbst aus.

Ich möchte auch hinzufügen, dass die for-Schleife, die Sie jetzt haben, nichts ändert. Es wird nur durch die Anzahl der Kinder iteriert und mPaintBackground festgelegt. Am Ende wird es mit dem Wert belassen, den es von der letzten Iteration erhält.

Ich denke, der beste Weg, um die Hintergrundfarbe zu handhaben Zeichnung im Adapter für die Listenansicht wäre, in welchem ​​Fall Sie getView() und tun eine Überprüfung auf der Grundlage der position Parameter außer Kraft setzen können:

int backgroundResource; 
if(position % 2 == 0){ 
    backgroundResource = getResources.getColor(android.R.color.WHITE); 
} else{ 
    backgorundResource = getResources.getColor(android.R.color.RED); 
} 
view.setBackground(backgroundResource); 

Natürlich , das obige ist nur Pseudocode, es muss möglicherweise an Ihr Projekt angepasst werden.


Die obige Lösung wird für bestehende Daten nur arbeiten. Wenn Sie eine alternierende Farbe benötigen, unabhängig davon, ob Daten vorhanden sind oder nicht, was ich jetzt verstehe, ist das, was Sie in dispatchDraw erreichen wollten. Ich werde sehr ehrlich sein, dass ich nicht 100% sicher bin, wie dies zu tun, und ich kann es nicht testen, aber ich glaube, die Schritte wie folgt gehen:

  • die Höhe des Listview Get
  • die Breite Get der ListView
  • Holen Sie die Höhe von einem Kind (listPreferredItemHeight, wenn Sie das verwenden. Wenn Sie Wrap-Inhalt verwenden, kann dies schwieriger sein, da Sie die Größe der Elemente nicht vorhersagen können, so dass abwechselnde Farben für eine leere ListView schwierig wäre).
  • Während in der ListView noch Platz ist, zeichnen Sie ein Rechteck.

Hinweis hier, dass Sie nicht Iterierte auf der Anzahl der Kinder basiert, kann, weil Sie jeder an dieser Stelle nicht haben könnte.

Pseudocode:

listViewWidth = getMeasuredWidth(); 
listViewHeight = getMeasuredHeight(); 
numChildren = getChildCount(); 
itemHeight = getItemHeight(); // See comments above, adjust this for your problem. 
currentTop = 0; // Used to keep track of the top of the rectangle we are drawing. 
currentBottom = itemHeight; // Used to keep track of the bottom rectangle we are currently drawing. 

int currentRectangle = 0; 
while(currentBottom <= listViewHeight){ 
    if(currentRectangle % 2 == 0){ 
     mPaintBackground.setColor(Color.WHITE); 
    } else{ 
     mPaintBackground.setColor(Color.RED); 
    } 

    Rect r = new Rect(0, currentBottom, getMeasuredWidth(), getMeasuredHeight()); 
    canvas.drawRect(r, mPaintBackground); 

    // Move to next 
    currentTop += itemHeight; 
    currentBottom += itemHeight; 
    currentRectangle++; 
} 
+0

Vielen Dank für Ihre schnelle Antwort. Aber wenn ich das benutze, dann zeigt es nur weiße Farbe. – Piyush

+0

@PiyushGupta bei welcher Linie maltest du den Hintergrund? In dem Code, den Sie haben, sieht es so aus, als ob Sie "getChildCount()" durchgehen und iterieren, aber nichts tun, außer die Hintergrundfarbe für den Hintergrund festzulegen, die auf dem Wert der letzten Iteration belassen wird. Wenn Sie 'getView()' in Ihrem Adapter aufrufen, können Sie eine Überprüfung basierend auf 'position' durchführen: http://developer.android.com/reference/android/widget/Adapter.html#getView (in, android. view.View, android.view.ViewGroup) – AdamMc331

+0

Ja, ich überprüfe es mit Position. Aber zumindest wenn die Daten leer sind, wird listView als eine mit alternierend weiß-rot bg Farbe angezeigt. aber es zeigt nicht! – Piyush

3

Es gibt einen kleinen Fehler in der Logik. hier ist der aktualisierte Code für diesen Abschnitt:

for (int i = 0; i < getChildCount(); i++) { 
     if (i % 2 == 0) { 
      view.setBackgroundColor(getResources.getColor(Color.WHITE)); 
     } else { 
      view.setBackgroundColor(getResources.getColor(Color.RED)); 
     } 
    } 

Die Überprüfung Zähler Regelgröße sein sollte, getChildCount wird immer die Gesamtanzahl der Elemente zurück, die ist, warum Sie immer gleiche Farbe sehen. Der obige eingefügte Code löst Ihr Problem. Aber dieser Code sollte in getView() für Ihre Adapterklasse sein, weil die getView() - Funktion in jeder Zeile zum Rendern aufgerufen wird. Ihre aktuelle Vorgehensweise ruft die Funktion nur einmal auf und Sie werden nicht das gewünschte Ergebnis erzielen.

+0

Wenn ich das benutze dann zeigt es nur weiße Farbe – Piyush

+0

Ich habe die Antwort aktualisiert. Dieses Code-Snippet sollte in der getView() Ihrer Adapterklasse enthalten sein. Ihr derzeitiges Code-Snippet bezieht sich auf das Listview-Widget, aber was genau Sie wollen, ist die Anpassung über die Zeile von Listview. –

1

Sie können den gleichen Effekt für eine Listview erstellen, indem Sie einfach eine benutzerdefinierte Adapter erstellen:

public class MyAlternateColorAdapter extends ArrayAdapter<SomeObject> { 

    private Context context; //Get the Context from the constructor 

    ... 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     View rowView = inflater.inflate(R.layout.rowlayout, parent, false); 

     if (position % 2 == 0) { 
      rowView.setBackgroundColor(Color.RED); // Or use rowView.setBackgroundResource(R.drawable.bg_red); where bg_red is a drawable with a selector to provide touch feedback 
     } else { 
      rowView.setBackgroundColor(Color.WHITE); 
     } 
     // Set the data of the row 
     ... 
    } 
} 
11

Endlich habe ich meine Antwort mit der großen Hilfe von @ McAdam331. Nachdem ich seinen Code benutzt habe, habe ich ein paar komische Sachen gemacht, aber danach habe ich den Code unter Verwendung dieses Codes repariert

 int listViewHeight = getMeasuredHeight(); 
     int itemHeight = lastChild.getMeasuredHeight(); 
     int currentTop = 0; 
     int currentBottom = lastChild.getBottom(); 

     int currentRectangle = 0; 
     while (currentBottom <= listViewHeight) { 
      if (currentRectangle % 2 == 0) { 
       mPaintBackground.setColor(Color.WHITE); 
      } else { 
       mPaintBackground.setColor(Color.parseColor("#f7f7f7")); 
      } 

      Rect r = new Rect(0, currentBottom, getMeasuredWidth(), getMeasuredHeight()); 
      canvas.drawRect(r, mPaintBackground); 

      // Move to next 
      currentTop += itemHeight; 
      currentBottom += itemHeight; 
      currentRectangle++; 
     } 
+0

Froh, dass das funktioniert, habe ich meine Antwort aktualisiert, um den richtigen 'Rect()' -Konstruktor wiederzugeben. – AdamMc331

+1

Danke nochmal. Ich habe deine Antwort akzeptiert !! – Piyush

Verwandte Themen