2012-11-08 13 views
38

Ho imparato che per massimizzare l'efficienza con le visualizzazioni di elenco di Android, si dovrebbero avere solo tante visualizzazioni di "righe" gonfiate necessarie per adattarsi allo schermo. Una volta che una vista è stata spostata dallo schermo, è necessario riutilizzarla nel metodo getView, controllando se convertView è nullo o meno.Riutilizzo di visualizzazioni in Android Listview con 2 layout diversi

Tuttavia, come è possibile implementare questa idea quando sono necessari 2 layout diversi per l'elenco? Diciamo che è un elenco di ordini e 1 layout è per gli ordini completati e l'altro è per gli ordini di processo.

Questo è un tutorial di esempio dell'idea che il mio codice sta utilizzando. Nel mio caso, avrei layout 2 righe: R.layout.listview_item_product_complete e 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

Recentemente ho riscontrato questo problema. Stavo usando 2 layout diversi per popolare un listview e ha portato a una completa anarchia. Ho ripassato il mio codice ancora e ancora, ma non sono riuscito a capire perché il layout sbagliato veniva riutilizzato. Alla fine, ho deciso di limitarmi a un solo * layout * per elenco, ma di modificare pesantemente quella vista in base al tipo di elemento. C'è molto che puoi fare per modificare gli elementi nel codice. –

risposta

83

È necessario lasciare dell'adattatore vista riciclatore sapere che non v'è più di un layout e come distinguere tra i due per ogni riga. Basta sovrascrivere questi metodi:

@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() all'interno getView(), in questo modo:

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... 

Watch Android Romain Guy discuss the view recycler a Google Talks.

+0

OK, quindi il titolare funge da copia dei puntatori alle diverse viste contenute nel layout della riga. Nel mio caso, entrambi i formati avranno gli stessi tipi di campo (solo formattati in modo diverso). Quindi ho bisogno di un solo titolare, giusto? E se un layout aveva un TextView e ImageView mentre l'altro aveva 2 TextView, avrei bisogno di 2 diversi supporti, no? – jamis0n

+2

"Nel mio caso, entrambi i layout avranno gli stessi tipi di campo (solo formattati in modo diverso), quindi avrò bisogno di un solo supporto." Sì, è corretto. "E se un layout aveva un TextView e ImageView mentre l'altro aveva 2 TextView, avrei bisogno di 2 diversi supporti, no?" Potresti avere due ViewHolders diversi oppure puoi combinare ViewHolders ma accedere solo ai membri appropriati per ogni layout. Ha senso? – Sam

+0

Sei l'uomo! Non funziona mai la prima volta! Tranne che con la tua guida Haha ... Quindi per mia comprensione, il titolare tiene semplicemente un puntatore a ogni vista nei layout di riga. Ottiene questi da layout appena gonfiati quando ConvertView è nullo OPPURE raccoglie magicamente questi puntatori dalla chiamata a 'holder = (ViewHolder) convertView.getTag();'. Sto comprendendo questo? Ho anche aggiornato il mio codice finale sopra ... Grazie ancora! – jamis0n

9

Non è necessario progettare una soluzione, basta sovrascrivere getItemViewType() e getViewTypeCount().

vedere il seguente post del blog per un esempio http://sparetimedev.blogspot.co.uk/2012/10/recycling-of-views-with-heterogeneous.html

come il blog spiega, Android non effettivamente garanzia che GetView riceverà il corretto tipo di vista.

+1

Non ho riscontrato questo problema ...È questo il tuo blog (ho notato che è scritto da "Andy")? Scommetto che 'getDirItem()' non è colpa del view recycler. – Sam

+0

Sì, è il mio blog. Scommessa - Quanto? :) Seriamente, il tuo commento mi ha fatto dubitare di me stesso, quindi sono andato a triplicare il mio codice e ho aggiunto un po 'più di debug. È sicuramente il caso che Android stia di tanto in tanto passando la vista sbagliata. L'indizio è che sto usando il metodo getItemViewType() all'interno di getView() per determinare il tipo. Quindi, anche se questo fosse sbagliato, a meno che non stia restituendo risultati casuali (piuttosto sicuro che non sia così!), Quindi Android sta passando la vista sbagliata. – Andy

+0

Non ho mai sentito parlare di questo problema prima ... Hai qualche fonte indipendente per confermare questo? Non lo vedo da solo e non riesco a trovarne. Senza vedere tutto il codice è impossibile vedere cosa sta realmente accadendo nel tuo codice. Ma per i principianti quali sono i valori di 'TYPE_DIR' e' TYPE_PIC'? – Sam

Problemi correlati