我遇到问题,我的自定义ArrayAdapter(下面的代码)正确填充了我的列表。根据我的理解,我的适配器仅在实例化时填充textviewResourceId,因为我正在使用构造函数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
}
}
的RowLayout:
<?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>
答案 0 :(得分: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子句中。
答案 1 :(得分: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);
答案 2 :(得分:1)
对我来说是正确的 - 唯一的事情:没有必要调用超类。尝试返回您的组合视图:
return row;
答案 3 :(得分: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);
}
}
答案 4 :(得分: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);
这可能有助于尝试自动滚动到最后一个的人。
N.B。 mListView.setSelection(position); 方法只有在我们将位置设置为最后时才能指向最后一个列表项。但是无法将列表项从forst填充到最后。
谢谢