2012-11-08 23 views
38

我瞭解到,爲了最大限度地提高Android列表視圖的效率,您應該只有儘可能多的虛擬「行」視圖才能適合屏幕。一旦視圖移出屏幕,您應該在getView方法中重新使用它,檢查convertView是否爲空。在Android Listview中重複使用2種不同佈局的視圖

但是,如果您需要2種不同的佈局以供列表使用,那麼如何實現這個想法?可以說它是一個訂單列表,1個佈局用於完成的訂單,另一個佈局用於處理訂單。

這是我的代碼正在使用的想法的示例教程。就我而言,我將有2列布局:R.layout.listview_item_product_completeR.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

我最近自己也遇到過這個問題。我使用2種不同的佈局來填充列表視圖,導致完全無政府狀態。我一遍又一遍地檢查了我的代碼,但無法弄清爲什麼錯誤的佈局被重新使用。最後,我決定堅持每個列表只有*一個佈局,但是根據項目類型大量修改該視圖。您可以使用代碼編輯項目。 –

回答

83

你需要讓適配器的看法回收知道,有一個以上的佈局,以及如何在兩個每一行之間的區別。簡單地重寫這些方法:

@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 
} 

一體化getItemViewType()getView(),就像這樣:

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

關注Android的羅曼蓋伊discuss the view recycler在谷歌舉行了會談。

+0

好的,所以持有者可以作爲指向行佈局中包含的不同視圖的指針的副本。在我的情況下,兩種佈局將具有相同的字段類型(只是格式不同)。所以我只需要一個持有人,對嗎?如果一個佈局有一個TextView和ImageView,而另一個有兩個TextView,我需要2個不同的持有者,不是嗎? – jamis0n

+2

「在我的情況下,兩種佈局將具有相同的字段類型(只是格式不同),所以我只需要一個持有者。」是的,這是正確的。 「如果一個佈局有一個TextView和ImageView,而另一個有兩個TextView,我需要兩個不同的持有者,不是嗎?」您可以擁有兩個不同的ViewHolders,或者可以合併ViewHolders,但只能訪問每個佈局的相應成員。那有意義嗎? – Sam

+0

你是男人!它從不第一次工作!除了你的指導哈哈......因此,爲了我的理解,持有人只是持有指向行佈局中的每個視圖的指針。它可以在ConvertView爲null時從新膨脹的佈局中獲取它們,或者通過調用'holder =(ViewHolder)convertView.getTag();'魔術般地拾取這些指針。我理解這一點嗎?我還更新了我上面的最終代碼...再次感謝! – jamis0n

9

無需自己設計解決方案,只需重寫getItemViewType()和getViewTypeCount()即可。

請參見下面的博客文章爲例http://sparetimedev.blogspot.co.uk/2012/10/recycling-of-views-with-heterogeneous.html

隨着博客解釋說,Android不實際保證是getView將獲得正確類型的視圖。

+1

我沒遇到過這個問題...這是你的博客嗎(我注意到它是由「Andy」寫的)?我會打賭'getDirItem()'是錯誤的,而不是視圖回收站。 – Sam

+0

是的,它是我的博客。賭注 - 多少錢? :)說真的,你的評論確實讓我懷疑自己,所以我去了三重檢查我的代碼+增加了更多的調試。 Android確實偶爾會傳遞錯誤觀點。線索是我使用getView()中的getItemViewType()方法來確定類型。所以,即使這是錯誤的,除非它返回隨機結果(很確定這不是這種情況!),然後Android傳遞錯誤的觀點。 – Andy

+0

我以前沒有聽說過這個問題......你有任何獨立的消息來證實這一點嗎?我沒有看到它自己,也找不到任何。如果沒有看到所有的代碼,就不可能看到代碼中發生了什麼。但對於初學者來說'TYPE_DIR'和'TYPE_PIC'的值是什麼? – Sam

相關問題