到目前为止,我一直在使用简单的ArrayAdapter
来显示ListView
中的一些项目。现在我还想在ListView
中的文本旁边显示图像。我有一个名为AsyncTask
的{{1}}来下载图片。下载工作正常,但我不知道如何在DownloadImageTask
中显示图片以及如何使用ListView
下载DownloadImageTask
中的图片。
这是ListView
我用来将图片下载到DownloadImageTask
:
ImageView
我还在private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public DownloadImageTask(ImageView bmImage) {
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return mIcon11;
}
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(result);
}
}
旁边定义了ImageView
,将图片下载到版面中。
ListView
我这样称呼<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000">
<ImageView
android:id="@+id/image1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ListView
android:id="@android:id/list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
:
DownloadImageTask
如何使用new DownloadImageTask((ImageView) findViewById(R.id.image1)).execute(url);
下载图片并将其显示在DownloadImageTask
文本旁边?
答案 0 :(得分:4)
要实现您想要的目标,您必须创建自定义Adapter
。要下载图像,我建议您使用像Picasso这样的库。 Picasso在下载图片时会处理几乎所有内容,而且实际上无法轻松使用它,您只需将其调用即可将图像下载到ImageView
:
Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
它已经缓存了图像,并且还可以通过多种方式转换图像。 Picasso是一个非常强大且易于使用的库。
Adapter
首先,我们需要为ListView
中的每一行创建一个布局,因为您要显示图像以及需要包含TextView
和{{1}的文本}:
ImageView
现在我们需要创建一个容器类 - 称为视图模型 - 来保存属于<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/imageView"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_margin="10dp"/>
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/imageView"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:textAlignment="gravity"
android:gravity="center"/>
</RelativeLayout>
每行的数据。在您的情况下,此视图模型包含您要显示的文本和图像的URL:
ListView
private class ExampleViewModel {
private String text;
private String imageUrl;
private ExampleViewModel(String text, String imageUrl) {
this.text = text;
this.imageUrl = imageUrl;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getImageUrl() {
return imageUrl;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
}
使用视图回收。我们可以通过使用名为&#34; view holder&#34;的模式来加快ListViews
的性能。基本上我们保存对每行内ListView
的引用,并将其附加到行本身。这样我们只需拨打一次昂贵的Views
。这个视图持有者类 - 我喜欢称它们为行 - 还包含一个名为findViewById()
的方法,用于将视图模型中的数据绑定到每行中的bind()
。我们需要引用Views
和TextView
,但毕加索还需要ImageView
。我还想将与此行关联的布局定义为行中的公共常量。
Context
最后,我们需要一个自定义private class ExampleRow {
// This is a reference to the layout we defined above
public static final int LAYOUT = R.layout.list_item;
private final Context context;
private final TextView textView;
private final ImageView imageView;
private ExampleRow(Context context, View convertView) {
this.context = context;
this.imageView = (ImageView) convertView.findViewById(R.id.imageView);
this.textView = (TextView) convertview.findViewById(R.id.textView);
}
public void bind(ExampleViewModel exampleViewModel) {
this.textView.setText(exampleViewModel.getText());
Picasso.with(this.context).load(exampleViewModel.getImageUrl()).into(this.imageView);
}
}
来完成这项工作,它并没有什么特别之处。唯一有趣的部分是Adapter
。如有必要,我会评论重要部分:
getView()
这就是你需要的一切。它几乎是public class ExampleAdapter extends BaseAdapter {
private final List<ExampleViewModel> viewModels;
private final Context context;
private final LayoutInflater inflater;
public ExampleAdapter(Context context) {
this.context = context;
this.inflater = LayoutInflater.from(context);
this.viewModels = new ArrayList<ExampleViewModel>();
}
public ExampleAdapter(Context context, List<ExampleViewModel> viewModels) {
this.context = context;
this.inflater = LayoutInflater.from(context);
this.viewModels = viewModels;
}
public List<ExampleViewModel> viewmodels() {
return this.viewModels;
}
@Override
public int getCount() {
return this.viewModels.size();
}
@Override
public ExampleViewModel getItem(int position) {
return this.viewModels.get(position);
}
@Override
public long getItemId(int position) {
// We only need to implement this if we have multiple rows with a different layout. All your rows use the same layout so we can just return 0.
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// We get the view model for this position
final ExampleViewModel viewModel = getItem(position);
ExampleRow row;
// If the convertView is null we need to create it
if(convertView == null) {
convertView = this.inflater.inflate(ExampleRow.LAYOUT, parent, false);
// In that case we also need to create a new row and attach it to the newly created View
row = new ExampleRow(this.context, convertView);
convertView.setTag(row);
}
// After that we get the row associated with this View and bind the view model to it
row = (ExampleRow) convertView.getTag();
row.bind(viewModel);
return convertView;
}
}
的最佳实践实现。它使用视图持有者模式以获得额外的性能,并与Adapter
的视图回收完美配合。它快速,简洁,容易,并且为开发人员犯下的错误留下了很小的空间,否则会导致ListView
减速。您可以完全区分要显示的数据(ListView
中的所有数据)及其显示方式(ExampleViewModel
中的数据)。适配器本身并不知道 - 应该是!
要使用上面的代码,我们首先需要创建包含我们想要显示的数据的视图模型:
ExampleRow
我们需要将所有这些行添加到ExampleViewModel firstRow = new ExampleViewModel("First Row". "http://http://upload.wikimedia.org/wikipedia/commons/6/6f/Freiburger_Alpen.JPG");
ExampleViewModel secondRow = new ExampleViewModel("Second Row". "http://blog.caranddriver.com/wp-content/uploads/2013/05/lamborghini_egoista_three_quarter_front_view.jpg");
ExampleViewModel thirdRow = new ExampleViewModel("Third Row". "http://4.bp.blogspot.com/-vXnf7GjcXmg/UfJZE9rWc2I/AAAAAAAAGRc/x2CIlHM9IAA/s1600/aphoto49721.jpg");
:
List
之后我们需要创建List<ExampleViewModel> viewModels = new ArrayList<ExampleViewModel>();
viewModels.add(firstRow);
viewModels.add(secondRow);
viewModels.add(thirdRow);
的实例并在构造函数中传递ExampleAdapter
个视图模型。最后,我们只需要将List
设置为Adapter
:
ListView
您可以稍后使用ExampleAdapter adapter = new ExampleAdapter(context, viewModels);
listView.setAdapter(adapter);
的{{1}}方法修改ListView
中显示的项目!您只需记住在修改视图模型后始终在viewmodels()
上调用ExampleAdapter
:
notifyDataSetChanged()
我希望我可以帮助您,如果您有任何其他问题,请随时提出来!
答案 1 :(得分:0)
您可以使用像Picasso或Universal Image Loader这样的外部库,它们会为您提供很多选择。由于他们管理缓存,您将能够从网址或任何时间加载图像并在几个地方显示它们。
你可以尝试:
我不确定,但也许您可以在下一个方式使用列表适配器的getView()方法中的DownloadClass:
new DownloadImageTask((ImageView) findViewById(R.id.image1)){
@Override
protected void onPostExecute(Bitmap bm) {
//set imageview src with your bitmap }}.execute(url);
}
}.execute(archivo,"investigacion");