3

カスタム ArrayAdapter (以下のコード) によってリストが正しく設定されない問題が発生しています。私が理解しているように、コンストラクターを使用しているため、アダプターはインスタンス化されたときにのみ textviewResourceId を設定していますが、 getViewAdapter(context, rowLayout, textViewResourceId, ArrayList<Items>)メソッドは、表示されていなかった行が表示されたときにのみ呼び出されます。

リストが最初に表示されたときに記事のタイトルだけが表示され、各行のすべてのビューが正しく入力されるようにするには、リストを下から上にスクロールする必要があるため、これが問題を引き起こしています (タスクは getView で行われます)。

誰かが私を正しい方向に向けることができますか? これをリファクタリングして、表示されている各行のすべてのビューがすぐに読み込まれるようにするにはどうすればよいですか?

私のカスタムアダプターへのコード:

import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class ArticleArrayAdapter extends ArrayAdapter<Article> {

    private final Context context;
    private final ArrayList<Article> articles;
    @SuppressWarnings("unused")
    private final int rowLayout;

    public ArticleArrayAdapter(Context context, int rowLayout, int textViewResourceId, ArrayList<Article> articles) {
        super(context, rowLayout, textViewResourceId, articles);
        this.rowLayout=rowLayout;
        this.context = context;
        this.articles = articles;
    }

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

        View row = convertView;
        if (row == null) {
            LayoutInflater inflater = ((Activity)context).getLayoutInflater();
            row = inflater.inflate(R.layout.affichageitem, null);
        }
        else {
            TextView viewTitre = (TextView)row.findViewById(R.id.titre);
            TextView viewAuteur = (TextView)row.findViewById(R.id.auteur);
            TextView viewDate = (TextView)row.findViewById(R.id.date);
            ImageView viewLogo = (ImageView)row.findViewById(R.id.category_logo);
            viewTitre.setText(articles.get(position).getTitle());
            viewAuteur.setText(articles.get(position).getCreator());
            viewDate.setText(articles.get(position).getDate());
            Drawable drawLogo = context.getResources().getDrawable(R.drawable.logocat);
            viewLogo.setImageDrawable(drawLogo);
        }
        return super.getView(position, convertView, parent);
    }
}

編集されたバージョン:

public class ArticleArrayAdapter extends ArrayAdapter<Article> {

    private final Context context;
    @SuppressWarnings("unused")
    private final int rowLayout;

    public ArticleArrayAdapter(Context context, int rowLayout,int textViewResourceId) {
        super(context, rowLayout, textViewResourceId);
        this.rowLayout=rowLayout;
        this.context = context;
    }

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

        View row = convertView;
        if (row == null) {
            LayoutInflater inflater = ((Activity)context).getLayoutInflater();
            row = inflater.inflate(R.layout.affichageitem, null);
        }
        else {
            TextView viewTitre = (TextView)row.findViewById(R.id.titre);
            TextView viewAuteur = (TextView)row.findViewById(R.id.auteur);
            TextView viewDate = (TextView)row.findViewById(R.id.date);
            ImageView viewLogo = (ImageView)row.findViewById(R.id.category_logo);
            viewTitre.setText(getItem(position).getTitle());
            viewAuteur.setText(getItem(position).getCreator());
            viewDate.setText(getItem(position).getDate());
            Drawable drawLogo = context.getResources().getDrawable(R.drawable.logocat);
            viewLogo.setImageDrawable(drawLogo);
        }
        return super.getView(position, convertView, parent); // <<- ONLY TITLES
        //return row; <<- EMPTY
    }
}

行レイアウト:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/category_logo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:contentDescription="@string/logo_desc"
        android:padding="20dp" />

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical"
        android:paddingLeft="5dp" >

        <TextView
            android:id="@+id/titre"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:textSize="18dp"
            android:textStyle="bold" />

        <LinearLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:gravity=""
            android:orientation="horizontal" >

            <TextView
            android:id="@+id/auteur"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:adjustViewBounds="true"
            android:textSize="12dp" />
            <TextView
            android:id="@+id/espace"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/espace"
            android:adjustViewBounds="true"
            android:textSize="12dp" />
            <TextView
            android:id="@+id/date"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:adjustViewBounds="true"
            android:textSize="12dp" />
        </LinearLayout>

    </LinearLayout>

</LinearLayout>
4

5 に答える 5

4

問題は、新しいビューを作成していないことです。何が起こるかというと、リスト ビューに使用される一定数のビューを Android が保持する場合があります。ビューは再利用されるため、すべてのビューを表示する前に「入力」することは不可能です。この行

if (view == null) {
    LayoutInflater inflater = ((Activity)context).getLayoutInflater();
    row = inflater.inflate(R.layout.affichageitem, null);
}

ビューがリサイクルされているかどうかを確認します。nullそうでないことを意味するため、 null を取得した場合は、新しいビューをインフレートする必要があります。そこまでは、コードは問題ありません。ただし、新しく膨張したビューであるかどうかにかかわらず、ビューにデータを入力する必要があります。したがって、else ステートメントを使用する必要はありません。

View row = convertView;
if (row == null) {
    LayoutInflater inflater = ((Activity)context).getLayoutInflater();
    row = inflater.inflate(R.layout.affichageitem, null);
}
TextView viewTitre = (TextView)row.findViewById(R.id.titre);
TextView viewAuteur = (TextView)row.findViewById(R.id.auteur);
TextView viewDate = (TextView)row.findViewById(R.id.date);
ImageView viewLogo = (ImageView)row.findViewById(R.id.category_logo);
viewTitre.setText(getItem(position).getTitle());
viewAuteur.setText(getItem(position).getCreator());
viewDate.setText(getItem(position).getDate());
Drawable drawLogo = context.getResources().getDrawable(R.drawable.logocat);
viewLogo.setImageDrawable(drawLogo);

return row;

一番下までスクロールしたときに機能した理由は、戻る途中でgetViewリサイクルを受け取りviews、それがあなたが持っていたelse節に飛び込んだからです。

于 2012-10-11T20:54:16.460 に答える
2

独自のコレクションを使用していますArrayList<Article>

ArrayAdaper<foo>すべてにはすでにデータ収集が組み込まれていることに注意してください。メソッドで追加add(foo)または削除できます。addAll(List<foo>)clear()

また、ListViewこのデータを監視し、このデータに変更が発生したときに更新できます。notifyDataSetChanged()または、アダプターで呼び出されたときに明示的に。

ここでの問題は、コンストラクターでデータを受け取り、さらに別のローカル変数に格納していnotifyDataSetChanged()て、呼び出されていないことです。Object はまだ作成中のため、コンストラクターから呼び出すことはできません。

したがって、コンストラクターでデータを受け入れないでください。内部getView()で使用getItem(position)してArticleアイテムを取得します。

次のようにデータを外部に追加します。

ArticleArrayAdapter adapter = new ArticleArrayAdapter(context,rowLayout,android.R.layout.simple_list_item_1);
adapter.addAll(articles);
myListView.setAdapter(adapter);
于 2012-10-11T17:42:00.193 に答える
1

私には正しいように見えます-唯一のこと:スーパークラスを呼び出す必要はありません。組み立てたビューを次のように返してみてください。

return row;
于 2012-10-11T17:27:05.733 に答える
0
@Override
public View getView(int position, View convertView, ViewGroup parent) {

    View row = convertView;
    if (row==null){
        LayoutInflater inflater = ((Activity)context).getLayoutInflater();
        row = inflater.inflate(R.layout.affichageitem, null);
         convertView.setTag(row);
    }else{
        TextView viewTitre = (TextView)row.findViewById(R.id.titre);
        TextView viewAuteur = (TextView)row.findViewById(R.id.auteur);
        TextView viewDate = (TextView)row.findViewById(R.id.date);
        ImageView viewLogo = (ImageView)row.findViewById(R.id.category_logo);
        viewTitre.setText(getItem(position).getTitle());
        viewAuteur.setText(getItem(position).getCreator());
        viewDate.setText(getItem(position).getDate());
        Drawable drawLogo = context.getResources().getDrawable(R.drawable.logocat);
        viewLogo.setImageDrawable(drawLogo);
    }
}
于 2014-04-25T17:07:06.533 に答える
0

このような問題がありました。また、リストの最後まで手動でスクロールしないと、すべてのビューが作成されないこともわかりました。表示されている項目を除いて、すべての項目が null だったので、プログラムでリストの最後までスクロールする必要がありました。

BaseAdapter クラスから MyAdapter を拡張しました。

mAdapter = new MyAdapter(this, mFinalContactList);
mListView.setAdapter(mAdapter);

作成されたすべてのリストビューで最後まで自動スクロールするには、次のコード行を使用しました。

mAdapter.notifyDataSetChanged();
mListView.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
mListView.smoothScrollToPosition(mFinalContactList.size()-1);

これは、最後まで自動スクロールしようとしている人の助けになるかもしれません。

NB mListView.setSelection(位置); メソッドは、位置を最後に設定した場合にのみ、最後のリスト項目を指すことができます。ただし、最初から最後までリスト項目を設定することはできません。

ありがとうございました

于 2016-11-06T02:15:59.040 に答える