2012-11-08 22 views
38

Androidのリストビューの効率を最大限にするためには、画面に表示するのに必要なだけの膨らんだ「行」ビューが必要です。ビューが画面外に移動したら、convertViewがnullかどうかを確認して、getViewメソッドでビューを再利用する必要があります。2つの異なるレイアウトでAndroid Listviewのビューを再利用

ただし、リストに2つの異なるレイアウトが必要な場合は、どのようにこのアイデアを実装できますか?注文の一覧と1つのレイアウトは完了した注文用で、もう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つの異なるレイアウトを使用してリストビューを作成しており、完全な無秩序をもたらしました。私は何度も何度も私のコードを見直しましたが、間違ったレイアウトが再利用された理由を理解できませんでした。最終的には、リストごとに1つの*レイアウトだけを固執することにしましたが、アイテムタイプに基づいてそのビューを大きく変更しました。コード内のアイテムを編集するためにできることはたくさんあります。 –

答えて

83

あなたは、アダプタのビューのリサイクル業者が複数のレイアウトとどのように各行のための2つを区別することがあることを知っている必要があります。

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:このように、getView()の内側に組み込むgetItemViewType()

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

:単にこれらのメソッドをオーバーライドします。

+0

OK、ホルダーは、行のレイアウトに含まれるさまざまなビューへのポインタのコピーとして機能します。私の場合、両方のレイアウトは同じフィールドタイプ(異なるフォーマット)になります。だから私は1人のホルダーしか必要としないでしょうか? 1つのレイアウトにTextViewとImageViewがあり、もう1つのレイアウトに2つのTextViewがある場合は、2つの異なるホルダーが必要ですか? – jamis0n

+2

"私の場合は、両方のレイアウトが同じフィールドタイプ(異なるフォーマット)になりますので、ホルダーは1つだけ必要です。"うん、これは正しい。 「一方のレイアウトにTextViewとImageViewがあり、もう一方のレイアウトに2つのTextViewがあると、2つの異なるホルダーが必要になるでしょうか?」 2つの異なる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

うん、その私のブログ。賭け - どれくらい? :)真剣に、あなたのコメントは自分自身を疑うようにしていたので、自分のコードを3回チェックして+さらにデバッグを追加しました。間違いなくAndroidが間違った視点を通過することは間違いありません。私がgetView()内のgetItemViewType()メソッドを使用して型を判別しているということです。だから、これが間違っていても、ランダムな結果が返ってこない限り(これはそうではないと確信しています!)、Androidは間違った視点を渡しています。 – Andy

+0

これまでにこの問題について聞いたことがありません...これを確認するための独立した情報源がありますか?私はそれを自分で見ていないし、何も見つけることができません。すべてのコードを見ることなく、コード内で実際に何が起こっているのかを見ることは不可能です。しかし、まずはTYPE_DIRとTYPE_PICの値は何ですか? – Sam