如何将imageview与listview中的某些文本组合在一起

时间:2014-06-26 15:03:25

标签: android android-layout listview android-listview

到目前为止,我一直在使用简单的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文本旁边?

2 个答案:

答案 0 :(得分:4)

要实现您想要的目标,您必须创建自定义Adapter。要下载图像,我建议您使用像Picasso这样的库。 Picasso在下载图片时会处理几乎所有内容,而且实际上无法轻松使用它,您只需将其调用即可将图像下载到ImageView

Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);

它已经缓存了图像,并且还可以通过多种方式转换图像。 Picasso是一个非常强大且易于使用的库。


1)实施自定义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()。我们需要引用ViewsTextView,但毕加索还需要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中的数据)。适配器本身并不知道 - 应该是!


2)如何使用

要使用上面的代码,我们首先需要创建包含我们想要显示的数据的视图模型:

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");