43

各行にアイコン ImageView と TextView を表示するカスタム ArrayAdapter に ListView があります。スクロールできるようにリストを十分に長くすると、順番が正しく表示されますが、下にスクロールし始めると、以前のエントリの一部が再表示され始めます。上にスクロールすると、古い順序が変わります。これを繰り返し行うと、最終的にリスト全体の順序がランダムに見えるようになります。したがって、リストをスクロールすると、子の順序が変更されるか、図面が正しく更新されません。

このようなことが起こる原因は何ですか?アイテムがユーザーに表示される順序は、ArrayList に追加された順序と同じにするか、少なくとも 1 つの静的な順序のままにする必要があります。より詳細な情報を提供する必要がある場合は、お知らせください。どんな助けでも大歓迎です。ありがとう。

4

4 に答える 4

60

私も同様の問題を抱えていましたが、カスタム リストの項目をクリックすると、画面上の項目が順番に逆になってしまいました。もう一度クリックすると、元の位置に戻ります。

これを読んだ後、 getView メソッドをオーバーロードしているコードをチェックしました。私はconvertedViewからビューを取得していましたが、それがnullの場合は、それが自分のものを構築するときです。ただし、ブレークポイントを配置した後、すべてのクリックでこのメソッドが呼び出され、その後のクリックでは、convertedView が null ではないため、項目が設定されていないことがわかりました。

それが何であったかの例を次に示します。


public View getView(int position, View convertView, ViewGroup parent)
{
    View view = convertView;
    if (view == null)
    {
        LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = vi.inflate(R.layout.listitemrow, null);

        RssItem rssItem = (RssItem) super.getItem(position);
        if (rssItem != null)
        {
            TextView title = (TextView) view.findViewById(R.id.rowtitle);
            if (title != null)
            {
                title.setText(rssItem.getTitle());
            }
        }
    }
    return view;
}

微妙な変更は、ビューの null チェックの右中かっこをインフレートの直後に移動することです。


public View getView(int position, View convertView, ViewGroup parent)
{
    View view = convertView;
    if (view == null)
    {
        LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = vi.inflate(R.layout.listitemrow, null);
    }
    RssItem rssItem = (RssItem) super.getItem(position);
    if (rssItem != null)
    {
        TextView title = (TextView) view.findViewById(R.id.rowtitle);
        if (title != null)
        {
            title.setText(rssItem.getTitle());
        }
    }
    return view;
}

これが、同じ問題を経験している他の人に役立つことを願っています。

于 2010-10-06T16:15:52.323 に答える
4

以下のfarcatsの答えをより一般的な方法でさらに明確にするために、ここに私の説明があります:

vi.inflate操作( XMLから行のレイアウトを解析し、適切なViewオブジェクトを作成するためにここで必要)は、効率のためにif(view == null)ステートメントでラップされるため、同じオブジェクトのインフレーションは発生しません。それが表示されるたびに何度も何度も。

ただし、getViewメソッドの他の部分は他のパラメーターを設定するために使用されるため、if(view == null)ステートメントに含めないでください。

同様に、このメソッドの他の一般的な実装では、一部のtextView、ImageView、またはImageButton要素に、findViewByIdを使用し、その後に.setTextまたは.setImageBitmap操作を使用してlist[position]の値を入力する必要あります。これらの操作は、インフレによって最初からビューを作成することと、nullでない場合は既存のビューを取得することの両方の後に行う必要があります。

このソリューションがBaseAdapterに適用される別の良い例は、BaseAdapterに表示され、スクロールするとListViewの順序が乱れます。

于 2012-01-10T18:56:38.867 に答える
3

ListView は、スクロール時にビュー オブジェクトを再利用します。getView メソッドをオーバーライドしていますか? すべてのビューに対して各プロパティを設定する必要があります。以前に持っていたものが記憶されているとは限りません。そのメソッドを投稿すると、誰かが間違っている部分を指摘してくれる可能性があります。

于 2010-06-02T05:43:28.913 に答える