3

我在让我的列表被我的自定义 ArrayAdapter(下面的代码)正确填充时遇到问题。据我了解,我的适配器仅在实例化时填充 textviewResourceId ,因为我使用的是 constructor Adapter(context, rowLayout, textViewResourceId, ArrayList<Items>),但只有在不可见的行变得可见时才调用 getView 方法。

这导致了一个问题,因为当我的列表首次显示时,只显示我的文章的标题,我必须一直向下滚动列表并向上滚动才能正确填充每行中的所有视图(因为任务在 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

我有这种类似的问题。我还发现,如果不手动滚动到列表的最后一个,则不会创建所有视图。除可见项目外,所有项目均为空。因此,我必须以编程方式向下滚动到列表的最后一个。

我从 BaseAdapter 类扩展了 MyAdapter。

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

为了自动滚动到最后创建的所有列表视图,我使用了以下代码行。

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

这可能会帮助一些尝试自动滚动到最后的人。

注意mListView.setSelection(position); 如果我们将位置设置为最后一个,方法只能指向最后一个列表项。但不能从 forst 到 last 填充列表项。

谢谢

于 2016-11-06T02:15:59.040 回答