2013-12-09 8 views
5

私は多くの同様の質問がstackoverflowに掲載されていることを知っていますので、高低を検索していないとは思わないでください。リストビューとリスト項目のライフサイクルを完全に理解するだけで問題は解決したと思います。私は、アウトバウンドまたはインバウンドの2種類のメッセージを含むことができるリストビューを持っています。もともと、私のlistViewは、メッセージのタイプ(アウトバウンド対インバウンド)によって異なる背景色を使用し、完璧に機能しました。今では、私のアプリケーションでは、リスト項目に異なる背景は必要ありませんが、実際には異なるリスト項目に対して異なるレイアウトが必要です。メッセージングアプリケーションのListViewは、スクロール後に間違ったlistItemレイアウトを表示します

これは私のアダプターのクリップです。

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

     View v = convertView; 

     SoapBoxMessage thisMessage = messages.get(position); 

     if (v == null) { 
      LayoutInflater inflater = (LayoutInflater) getContext() 
        .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

      if (thisMessage.isOutbound()) { 
       v = inflater.inflate(R.layout.outbound_row, null); 

      } else { 
       v = inflater.inflate(R.layout.inbound_row, null); 

      } 
     } 

答えて

2

問題は、リストビューはそうビューをリサイクルされたビューがnullであるかどうかをチェックするとき、それはそれは

をリサイクルする際にビューがnullではないので、あなたがビューを膨らませる必要があると渡す文句を言わないということですgetViewが呼び出されるたびに、基本的に取り除くif(v == null)

+0

こんにちは...このような単純な間違いは私の一部です。それに気づいてくれてありがとう。パフォーマンスが最適であることを確認するために何か他のことをすることをお勧めしますか? – GuyLeStack

+0

実際にはifステートメントを単に削除するだけでレイアウトの問題は解決されますが、後でアダプタで動的に追加される他のビューではさらに問題が発生します。アイデア? – GuyLeStack

+0

その他のビューは?コードを見ることはできますか? –

1

リサイクルが起こっているからです。常にgetView方法で値をリセットするか、開始することを忘れないでください、また

public View getView(int position, View convertView, ViewGroup parent) { 
    ViewHolder holder = null; 
    SoapBoxMessage thisMessage = messages.get(position); 

    if (convertView == null) { 
     LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE); 
     convertView = mInflater.inflate(R.layout.listview_feedlog_item, null); 

     holder = new ViewHolder(); 
     holder.txtTime = (TextView) convertView.findViewById(R.id.textTime); 
     holder.txtDate = (TextView) convertView.findViewById(R.id.textDate); 

     convertView.setTag(holder); 
    } else 
     holder = (ViewHolder) convertView.getTag(); 

    // I don't know how your SoapBoxMessage is made up so here are two sample methods 
    holder.txtTime.setText(thisMessage.getTime()); 
    holder.txtDate.setText(thisMessage.getDate()); 

    return convertView; 
} 

/* private view holder class */ 
private class ViewHolder { 
    TextView txtTime; 
    TextView txtDate; 
} 

:あなたはこれらの線に沿って何かが必要になります。 Viewはリサイクルすることができるので、それは以前の人生の特性を持ち運ぶかもしれません。

+0

私は@tyczjソリューションに従っていますが、レイアウトの問題は修正されていますが、後でアダプタで動的に追加される他のビューではさらに問題が生じます。アイデア? – GuyLeStack

+0

'if(v == null)'を削除するのは良い解決策ではないと思います。それは少なくとも、望ましい解決策ではありません。今あなたの質問を読んで、私はあなたがやろうとしていることを見て、あなたはいくつかの方法を実装する必要があります。この回答を見てください:http://stackoverflow.com/questions/4777272/android-listview-with-different-layout-for-each-row – Mike

4

アダプターは、リサイクルの問題を解決するさまざまなViewItemTypesをサポートできます。リストビューは、各位置についてViewItemTypesを尊重し、それが唯一のViewHolderを使用してみてくださいその位置

+0

これに続いて、それでも運がありません。動的に追加されたビュー(getView()で後で追加されたもの)はまだまだ混乱していますが、表示されますが、スクロールを開始してから離れることになります。 – GuyLeStack

+0

動的に追加されたビューは2つの異なるレイアウトを使用する場合とは異なります。基本的に2つのパス。 1.渡されたconvertviewは無視して、常にアイテムの位置に適したビューを作成してください。 2。リサイクルされたビューを使用することはできますが、以前に追加されたものは削除または修正する必要があります。リサイクルの見解は教科書のようなもので、前の所有者(アイテム)のメモを消去してクリーンブックを入手する必要があります。 – dangVarmit

+0

あなたが言及した最初のルートに行きたいと思います。だから私はする必要があります:1.私のリストアイテム(インバウンドvアウトバウンド)の適切なレイアウトを設定する2.すべての私のダイナミックビューを適用する場合は追加3.完了? – GuyLeStack

2

ための正しいビュータイプのconvertviewを提供しますので、あなたがリサイクルビューを心配する必要はありません

static public enum LAYOUT_TYPE { 
    INBOUND, 
    OUTBOUND 
} 

@Override 
public int getViewTypeCount() { 
    return LAYOUT_TYPE.values().length; 
} 

@Override 
public int getItemViewType (int position) { 
    if (messages.get(position).isOutbound()) 
     return LAYOUT_TYPE.OUTBOUND.ordinal(); 
    else 
     return LAYOUT_TYPE.INBOUND.ordinal(); 
} 

@Override 
public View getView (int position, View convertView, ViewGroup parent) { 
    LAYOUT_TYPE itemType = LAYOUT_TYPE.values()[getItemViewType(position)]; 
    ... (code until inflater) 
    switch (itemType){ 
    case INBOUND: 
      convertview = /inflate & configure inbound layout 
      break; 
    case OUTBOUND: 
      convertview = /inflate & configure outbound layout 
      break; 
    } 

このような:これは良い習慣であるか、if (v == null)を削除しても問題が解決するかどうかではない

ViewHolder holder; 

public View getView(int position, View convertView, ViewGroup parent) { 
    convertView = null; 
    SoapBoxMessage thisMessage = messages.get(position); 

    if (convertView == null) { 
     LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

     if (thisMessage.isOutbound()) { 
      convertView = inflater.inflate(R.layout.outbound, null, false); 

      //specific to your outbound layout 
      holder = new ViewHolder(); 
      holder.text= (TextView)convertView.findViewById(R.id.textview); 
      holder.group = (RadioGroup)convertView.findViewById(R.id.toggleGroup); 
      holder.toggle = (ToggleButton)convertView.findViewById(R.id.toggleButton); 
     } else { 
      convertView = inflater.inflate(R.layout.inbound, null, false); 

      //specific to your inbound layout 
      holder = new ViewHolder(); 
      holder.text= (TextView)convertView.findViewById(R.id.textview); 
      holder.group = (RadioGroup)convertView.findViewById(R.id.toggleGroup); 
      holder.toggle = (ToggleButton)convertView.findViewById(R.id.toggleButton); 
     } 
     convertView.setTag(holder); 
    } 
    else{ 
     holder = (ViewHolder) convertView.getTag(); 
    } 

    //Here you can set the text or other code you want to implement 
    holder.text.setText("Whatever!"); 

    return convertView; 
} 

static class ViewHolder { 
    //TODO put components you use like: 
    TextView text; 
    RadioGroup group; 
    ToggleButton toggle; 
} 
+0

convertViewは常にnullになります... else { holder =(ViewHolder)convertView.getTag();を作成します。 } '役に立たない? – GuyLeStack

+1

@GuyLeStack 'getViewTypeCount'メソッドとgetItemViewTypeメソッドを正しくオーバーライドすると、nullになりません。 – vorrtex

+0

しかし、答えの2行目は 'convertView = null;'と答えています – GuyLeStack

0

。とにかく、ビューを再膨張させる必要があります。

関連する問題