如何在Android的ListView中显示图像列表?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/459729/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to display a list of images in a ListView in Android?
提问by
How do I display a list of images using the ListView? I am downloading the images at run time. The total number of images is not fixed.
如何使用 ListView 显示图像列表?我正在运行时下载图像。图像总数不固定。
回答by srakyi
I'd start with something like this (and if there is something wrong with my code, I'd of course appreciate any comment):
我会从这样的事情开始(如果我的代码有问题,我当然会感谢任何评论):
public class ItemsList extends ListActivity {
private ItemsAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.items_list);
this.adapter = new ItemsAdapter(this, R.layout.items_list_item, ItemManager.getLoadedItems());
setListAdapter(this.adapter);
}
private class ItemsAdapter extends ArrayAdapter<Item> {
private Item[] items;
public ItemsAdapter(Context context, int textViewResourceId, Item[] items) {
super(context, textViewResourceId, items);
this.items = items;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.items_list_item, null);
}
Item it = items[position];
if (it != null) {
ImageView iv = (ImageView) v.findViewById(R.id.list_item_image);
if (iv != null) {
iv.setImageDrawable(it.getImage());
}
}
return v;
}
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
this.adapter.getItem(position).click(this.getApplicationContext());
}
}
E.g. extending ArrayAdapter with own type of Items (holding information about your pictures) and overriden getView()
method, that prepares view for items within list. There is also method add()
on ArrayAdapter to add items to the end of the list.
例如,使用自己的项目类型(保存有关您的图片的信息)和覆盖getView()
方法扩展 ArrayAdapter,为列表中的项目准备视图。add()
ArrayAdapter 上还有一个方法可以将项目添加到列表的末尾。
R.layout.items_list
is simple layout with ListView
R.layout.items_list
是简单的布局 ListView
R.layout.items_list_item
is layout representing one item in list
R.layout.items_list_item
是代表列表中一项的布局
回答by Ashish Anand
package studRecords.one;
import java.util.List;
import java.util.Vector;
import android.app.Activity;
import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;
import android.net.ParseException;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
public class studRecords extends ListActivity
{
static String listName = "";
static String listUsn = "";
static Integer images;
private LayoutInflater layoutx;
private Vector<RowData> listValue;
RowData rd;
static final String[] names = new String[]
{
"Name (Stud1)", "Name (Stud2)",
"Name (Stud3)","Name (Stud4)"
};
static final String[] usn = new String[]
{
"1PI08CS016","1PI08CS007","1PI08CS017","1PI08CS047"
};
private Integer[] imgid =
{
R.drawable.stud1,R.drawable.stud2,R.drawable.stud3,
R.drawable.stud4
};
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.mainlist);
layoutx = (LayoutInflater) getSystemService(
Activity.LAYOUT_INFLATER_SERVICE);
listValue = new Vector<RowData>();
for(int i=0;i<names.length;i++)
{
try
{
rd = new RowData(names[i],usn[i],i);
}
catch (ParseException e)
{
e.printStackTrace();
}
listValue.add(rd);
}
CustomAdapter adapter = new CustomAdapter(this, R.layout.list,
R.id.detail, listValue);
setListAdapter(adapter);
getListView().setTextFilterEnabled(true);
}
public void onListItemClick(ListView parent, View v, int position,long id)
{
listName = names[position];
listUsn = usn[position];
images = imgid[position];
Intent myIntent = new Intent();
Intent setClassName = myIntent.setClassName("studRecords.one","studRecords.one.nextList");
startActivity(myIntent);
}
private class RowData
{
protected String mNames;
protected String mUsn;
protected int mId;
RowData(String title,String detail,int id){
mId=id;
mNames = title;
mUsn = detail;
}
@Override
public String toString()
{
return mNames+" "+mUsn+" "+mId;
}
}
private class CustomAdapter extends ArrayAdapter<RowData>
{
public CustomAdapter(Context context, int resource,
int textViewResourceId, List<RowData> objects)
{
super(context, resource, textViewResourceId, objects);
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder = null;
TextView title = null;
TextView detail = null;
ImageView i11=null;
RowData rowData= getItem(position);
if(null == convertView)
{
convertView = layoutx.inflate(R.layout.list, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
}
holder = (ViewHolder) convertView.getTag();
i11=holder.getImage();
i11.setImageResource(imgid[rowData.mId]);
title = holder.gettitle();
title.setText(rowData.mNames);
detail = holder.getdetail();
detail.setText(rowData.mUsn);
return convertView;
}
private class ViewHolder
{
private View mRow;
private TextView title = null;
private TextView detail = null;
private ImageView i11=null;
public ViewHolder(View row)
{
mRow = row;
}
public TextView gettitle()
{
if(null == title)
{
title = (TextView) mRow.findViewById(R.id.title);
}
return title;
}
public TextView getdetail()
{
if(null == detail)
{
detail = (TextView) mRow.findViewById(R.id.detail);
}
return detail;
}
public ImageView getImage()
{
if(null == i11)
{
i11 = (ImageView) mRow.findViewById(R.id.img);
}
return i11;
}
}
}
}
//mainlist.xml
//主列表.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<ListView
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
回答by Arunkumar T
Here is the simple ListView with different images. First of all you have to copy the different kinds of images and paste it to the res/drawable-hdpi in your project. Images should be (.png)file format. then copy this code.
这是具有不同图像的简单 ListView。首先,您必须复制不同类型的图像并将其粘贴到项目中的 res/drawable-hdpi。图像应为 (.png) 文件格式。然后复制这个代码。
In main.xml
在 main.xml 中
<?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="fill_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/textview"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<ListView
android:id="@+id/listview"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
create listview_layout.xml and paste this code
创建 listview_layout.xml 并粘贴此代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<ImageView
android:id="@+id/flag"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/hello"
android:paddingTop="10dp"
android:paddingRight="10dp"
android:paddingBottom="10dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15dp"
android:text="TextView1" />
<TextView
android:id="@+id/cur"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="10dp"
android:text="TextView2" />
</LinearLayout>
In your Activity
在您的活动中
package com.test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;
import android.widget.SimpleAdapter;
public class SimpleListImageActivity extends Activity {
// Array of strings storing country names
String[] countries = new String[] {
"India",
"Pakistan",
"Sri Lanka",
"China",
"Bangladesh",
"Nepal",
"Afghanistan",
"North Korea",
"South Korea",
"Japan"
};
// Array of integers points to images stored in /res/drawable-hdpi/
//here you have to give image name which you already pasted it in /res/drawable-hdpi/
int[] flags = new int[]{
R.drawable.image1,
R.drawable.image2,
R.drawable.image3,
R.drawable.image4,
R.drawable.image5,
R.drawable.image6,
R.drawable.image7,
R.drawable.image8,
R.drawable.image9,
R.drawable.image10,
};
// Array of strings to store currencies
String[] currency = new String[]{
"Indian Rupee",
"Pakistani Rupee",
"Sri Lankan Rupee",
"Renminbi",
"Bangladeshi Taka",
"Nepalese Rupee",
"Afghani",
"North Korean Won",
"South Korean Won",
"Japanese Yen"
};
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Each row in the list stores country name, currency and flag
List<HashMap<String,String>> aList = new ArrayList<HashMap<String,String>>();
for(int i=0;i<10;i++){
HashMap<String, String> hm = new HashMap<String,String>();
hm.put("txt", "Country : " + countries[i]);
hm.put("cur","Currency : " + currency[i]);
hm.put("flag", Integer.toString(flags[i]) );
aList.add(hm);
}
// Keys used in Hashmap
String[] from = { "flag","txt","cur" };
// Ids of views in listview_layout
int[] to = { R.id.flag,R.id.txt,R.id.cur};
// Instantiating an adapter to store each items
// R.layout.listview_layout defines the layout of each item
SimpleAdapter adapter = new SimpleAdapter(getBaseContext(), aList, R.layout.listview_layout, from, to);
// Getting a reference to listview of main.xml layout file
ListView listView = ( ListView ) findViewById(R.id.listview);
// Setting the adapter to the listView
listView.setAdapter(adapter);
}
}
This is the full code.you can make changes to your need... Comments are welcome
这是完整的代码。您可以根据需要进行更改...欢迎评论
回答by e4c5
Six years on, this is still at the top for some searches. Things have changed a lot since then. Now the defacto standard is more or less to use Volleyand the NetworkImageView which takes care of the heavy lifting for you.
六年过去了,这仍然是一些搜索的顶部。从那时起,情况发生了很大变化。现在,事实上的标准或多或少是使用 Volley和 NetworkImageView 来处理繁重的工作。
Assuming that you already have your Apaters, Loaders and ListFragments setup properly, this official google tutorialexplains how to use NetworkImageView to load the images. Images are automatically loaded in a background thread and the view updated on the UI thread. It even supports caching.
假设您已经正确设置了 Apaters、Loaders 和 ListFragments,这个google 官方教程解释了如何使用 NetworkImageView 加载图像。图像在后台线程中自动加载,并在 UI 线程上更新视图。它甚至支持缓存。
回答by AgileYogi
I came up with a solution that I call “BatchImageDownloader” that has served well. Here's a quick summary of how it is used:
我想出了一个我称之为“BatchImageDownloader”的解决方案,效果很好。以下是如何使用它的快速摘要:
Keep a global HashMap (ideally in your Application object) that serves as a cache of drawable objects
In the getView() method of your List Adapter, use the drawable from the cache for populating the ImageView in your list item.
Create an instance of BatchImageDownloader, passing in your ListView Adapter
Call addUrl() for each image that needs to be fetched/displayed
When done, call execute(). This fires an AsyncTask that fetches all images, and as each image is fetched and added to the cache, it refreshes your ListView (by calling notifyDataSetChanged())
保留一个全局 HashMap(最好在您的 Application 对象中)作为可绘制对象的缓存
在列表适配器的 getView() 方法中,使用缓存中的可绘制对象填充列表项中的 ImageView。
创建一个 BatchImageDownloader 实例,传入你的 ListView Adapter
为每个需要获取/显示的图像调用 addUrl()
完成后,调用execute()。这会触发一个获取所有图像的 AsyncTask,并且随着每个图像被获取并添加到缓存中,它会刷新您的 ListView(通过调用 notifyDataSetChanged())
The approach has the following advantages:
该方法具有以下优点:
- A single worker thread is used to fetch all images, rather than a separate thread for each image/view
- Once an image is fetched, all list items that use it are instantly updated
- The code does not access the Image View in your List Item directly – instead it triggers a listview refresh by calling notifyDataSetChanged() on your List Adapter, and the getView() implementation simply pulls the drawable from the cache and displays it. This avoids the problems associated with recycled View objects used in ListViews.
- 单个工作线程用于获取所有图像,而不是每个图像/视图的单独线程
- 获取图像后,所有使用它的列表项都会立即更新
- 代码不直接访问列表项中的图像视图——而是通过调用列表适配器上的 notifyDataSetChanged() 触发列表视图刷新,而 getView() 实现只是从缓存中提取可绘制对象并显示它。这避免了与在 ListView 中使用的回收 View 对象相关的问题。
Here is the source code of BatchImageDownloader:
这是 BatchImageDownloader 的源代码:
package com.mobrite.androidutils;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.widget.BaseAdapter;
public class BatchImageDownloader extends AsyncTask<Void, Void, Void> {
List<String> imgUrls = new ArrayList<String>();
BaseAdapter adapter;
HashMap<String, Drawable> imageCache;
public BatchImageDownloader(BaseAdapter adapter,
HashMap<String, Drawable> imageCache) {
this.adapter = adapter;
this.imageCache = imageCache;
}
public void addUrl(String url) {
imgUrls.add(url);
}
@Override
protected Void doInBackground(Void... params) {
for (String url : imgUrls) {
if (!imageCache.containsKey(url)) {
Drawable bm = downloadImage(url);
if (null != bm) {
imageCache.put(url, bm);
publishProgress();
}
}
}
return null;
}
@Override
protected void onProgressUpdate(Void... values) {
adapter.notifyDataSetChanged();
}
@Override
protected void onPostExecute(Void result) {
adapter.notifyDataSetChanged();
}
public Drawable downloadImage(String url) {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet request = new HttpGet(url);
try {
HttpResponse response = httpClient.execute(request);
InputStream stream = response.getEntity().getContent();
Drawable drawable = Drawable.createFromStream(stream, "src");
return drawable;
} catch (ClientProtocolException e) {
e.printStackTrace();
return null;
} catch (IllegalStateException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
回答by JRL
To get the data from the database, you'd use a SimpleCursorAdapter
.
要从数据库中获取数据,您需要使用SimpleCursorAdapter
.
I think you can directly bind the SimpleCursorAdapter
to a ListView
- if not, you can create a custom adapter class that extends SimpleCursorAdapter with a custom ViewBinder
that overrides setViewValue
.
我认为您可以直接将 绑定SimpleCursorAdapter
到 a ListView
- 如果没有,您可以创建一个自定义适配器类,该类扩展 SimpleCursorAdapter 并自定义ViewBinder
覆盖setViewValue
.
Look at the Notepadtutorial to see how to use a SimpleCursorAdapter
.
查看记事本教程以了解如何使用SimpleCursorAdapter
.
回答by JRL
File name should match the layout id which in this example is : items_list_item.xml in the layout folder of your application
文件名应与布局 ID 匹配,在本例中为:应用程序布局文件夹中的 items_list_item.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<ImageView android:id="@+id/R.id.list_item_image"
android:layout_width="100dip"
android:layout_height="wrap_content" />
</LinearLayout>
回答by JRL
We need to implement two layouts. One to hold listview and another to hold row item of listview. Implement your own custom adapter. Idea is to include one textview and one imageview.
我们需要实现两种布局。一个用于保存列表视图,另一个用于保存列表视图的行项目。实现您自己的自定义适配器。想法是包括一个文本视图和一个图像视图。
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View single_row = inflater.inflate(R.layout.list_row, null,
true);
TextView textView = (TextView) single_row.findViewById(R.id.textView);
ImageView imageView = (ImageView) single_row.findViewById(R.id.imageView);
textView.setText(color_names[position]);
imageView.setImageResource(image_id[position]);
return single_row;
}
Next we implement functionality in main activity to include images and text data dynamically during runtime. You can pass dynamically created text array and image id array to the constructor of custom adapter.
接下来,我们在主要活动中实现功能以在运行时动态地包含图像和文本数据。您可以将动态创建的文本数组和图像 id 数组传递给自定义适配器的构造函数。
Customlistadapter adapter = new Customlistadapter(this, image_id, text_name);