2012-11-08 20 views
38

Ich habe gelernt, dass zur Maximierung der Effizienz mit Android-Listenansichten nur so viele aufgeblähte Zeilenansichten vorhanden sein sollten, wie auf dem Bildschirm angezeigt werden müssen. Sobald eine Ansicht vom Bildschirm verschwunden ist, sollten Sie sie erneut in Ihrer getView-Methode verwenden und prüfen, ob convertView Null ist oder nicht.Ansichten in Android Listview mit zwei verschiedenen Layouts wiederverwenden

Wie können Sie diese Idee jedoch implementieren, wenn Sie zwei verschiedene Layouts für die Liste benötigen? Sagen wir, es ist eine Liste von Bestellungen und 1 Layout ist für abgeschlossene Bestellungen und das andere Layout ist für in Bearbeitung Bestellungen.

Dies ist ein Beispiel-Tutorial der Idee, die mein Code verwendet. In meinem Fall würde ich 2 Reihe Layouts: R.layout.listview_item_product_complete und R.layout.listview_item_product_inprocess

public View getView(int position, View convertView, ViewGroup parent) { 

ViewHolder holder = null; 

if (convertView == null) { 
    holder = new ViewHolder(); 
    if(getItemViewType(position) == COMPLETE_TYPE_INDEX) { 
     convertView = mInflator.inflate(R.layout.listview_item_product_complete, null); 
     holder.mNameTextView = (TextView) convertView.findViewById(R.list.text_complete); 
     holder.mImgImageView = (ImageView) convertView.findViewById(R.list.img_complete); 
    } 
    else { // must be INPROCESS_TYPE_INDEX 
     convertView = mInflator.inflate(R.layout.listview_item_product_inprocess, null); 
     holder.mNameTextView = (TextView) convertView.findViewById(R.list.text_inprocess); 
     holder.mImgImageView = (ImageView) convertView.findViewById(R.list.img_inprocess); 
    } 
    convertView.setTag(holder); 
} else { 
    holder = (ViewHolder) convertView.getTag(); 
} 
    thisOrder = (Order) myOrders.getOrderList().get(position); 
    // If using different views for each type, use an if statement to test for type, like above 
    holder.mNameTextView.setText(thisOrder.getNameValue()); 
    holder.mImgImageView.setImageResource(thisOrder.getIconValue()); 
    return convertView; 
} 

public static class ViewHolder { 
    public TextView mNameTextView; 
    public ImageView mImgImageView; 
} 
+0

Ich bin dieses Problem vor kurzem selbst begegnet. Ich benutzte 2 verschiedene Layouts, um eine Listenansicht zu füllen, und das führte zu vollständiger Anarchie. Ich habe meinen Code immer wieder durchgegangen, konnte aber nicht herausfinden, warum das falsche Layout wiederverwendet wurde. Am Ende entschied ich mich, nur mit einem * Layout pro Liste zu arbeiten, aber diese Ansicht basierend auf dem Elementtyp stark zu modifizieren. Es gibt viel, was Sie tun können, um Elemente im Code zu bearbeiten. –

Antwort

83

Sie müssen die Adapter Ansicht Recycler wissen lassen, dass es mehr als ein Layout ist und wie zwischen den beiden für jede Zeile zu unterscheiden. außer Kraft setzen Sie einfach diese Methoden:

@Override 
public int getItemViewType(int position) { 
    // Define a way to determine which layout to use, here it's just evens and odds. 
    return position % 2; 
} 

@Override 
public int getViewTypeCount() { 
    return 2; // Count of different layouts 
} 

Incorporate getItemViewType() innen getView(), wie folgt aus:

if (convertView == null) { 
    // You can move this line into your constructor, the inflater service won't change. 
    mInflater = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE); 
    if(getItemViewType(position) == 0) 
     convertView = mInflater.inflate(R.layout.listview_item_product_complete, parent, false); 
    else 
     convertView = mInflater.inflate(R.layout.listview_item_product_inprocess, parent, false); 
    // etc, etc... 

Uhr Android Romain Guy discuss the view recycler bei Google Talks.

+0

OK, daher dient der Halter als Kopie der Zeiger auf die verschiedenen Ansichten, die im Layout der Zeile enthalten sind. In meinem Fall haben beide Layouts die gleichen Feldtypen (nur anders formatiert). Also brauche ich nur einen Halter, richtig? Und wenn ein Layout ein TextView und ImageView hätte, während das andere zwei TextViews hätte, würde ich zwei verschiedene Halter benötigen, nein? – jamis0n

+2

"In meinem Fall haben beide Layouts die gleichen Feldtypen (nur anders formatiert). Also brauche ich nur einen Halter." Yup, das ist richtig. "Und wenn ein Layout ein TextView und ein ImageView hätte, während das andere zwei TextViews hätte, würde ich zwei verschiedene Halter benötigen, nicht?" Sie können zwei verschiedene ViewHolder verwenden oder die ViewHolder kombinieren, aber nur auf die entsprechenden Elemente für jedes Layout zugreifen. Ist das sinnvoll? – Sam

+0

Du bist der Mann! Es funktioniert nie das erste Mal! Außer mit Ihrer Anleitung Haha ... Also zu meinem Verständnis hält Inhaber nur einen Zeiger auf jede Ansicht in den Zeilenlayouts. Es bekommt entweder diese von neu aufgeblähten Layouts, wenn ConvertView null ist oder es magisch diese Zeiger vom Aufruf von 'holder = (ViewHolder) convertView.getTag();'. Verstehe ich das? Ich habe auch meinen letzten Code oben aktualisiert ... Danke nochmal! – jamis0n

9

Keine Notwendigkeit, eine Lösung selbst zu konstruieren, überschreiben Sie einfach getItemViewType() und getViewTypeCount().

Sehen Sie im folgenden Blog-Post für ein Beispiel http://sparetimedev.blogspot.co.uk/2012/10/recycling-of-views-with-heterogeneous.html

Wie der Blog erklärt, ist Android nicht wirklich Garantie die getView wird die richtige Art der Ansicht erhalten.

+1

Ich habe dieses Problem nicht erlebt ...Ist das dein Blog (ich habe festgestellt, dass es von "Andy" geschrieben wurde)? Ich würde wetten, dass 'getDirItem()' nicht den View Recycler trifft. – Sam

+0

Ja, es ist mein Blog. Wette - Wie viel? :) Im Ernst, dein Kommentar hat mich dazu gebracht, an mir selbst zu zweifeln, also ging ich und verdreifachte meinen Code und fügte noch mehr Debugging hinzu. Es ist definitiv so, dass Android gelegentlich die falsche Sichtweise passiert. Der Schlüssel ist, dass ich die Methode getItemViewType() in getView() verwende, um den Typ zu bestimmen. Auch wenn dies falsch war, es sei denn, es gibt zufällige Ergebnisse zurück (ziemlich sicher, dass dies nicht der Fall ist!), Dann übergibt Android die falsche Ansicht. – Andy

+0

Ich habe noch nie von diesem Problem gehört ... Haben Sie unabhängige Quellen, um dies zu bestätigen? Ich sehe es selbst nicht und kann keines finden. Ohne den ganzen Code zu sehen, ist es unmöglich zu sehen, was wirklich in Ihrem Code passiert. Aber was sind die Werte für 'TYPE_DIR' und' TYPE_PIC'? – Sam

Verwandte Themen