【问题标题】:How to display a list of images in a ListView in Android?如何在 Android 的 ListView 中显示图像列表?
【发布时间】:2010-10-02 08:43:46
【问题描述】:

如何使用 ListView 显示图像列表?我在运行时下载图像。图片总数不固定。

【问题讨论】:

标签: android listview android-image


【解决方案1】:

我会从这样的事情开始(如果我的代码有问题,我当然会感谢任何评论):

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());
}
}

例如使用自己的 Items 类型扩展 ArrayAdapter(保存有关您的图片的信息)并覆盖 getView() 方法,该方法为列表中的项目准备视图。 ArrayAdapter 上还有 add() 方法可以将项目添加到列表的末尾。

R.layout.items_list 是带有ListView 的简单布局

R.layout.items_list_item 是表示列表中一项的布局

【讨论】:

  • findViewById 不是每次都找到相同的视图吗?
  • 当你在一个View上调用findViewById,它会找到一个子view;由于您使用 getView() 获得不同的视图,因此每次都会找到不同的子视图。
  • 你能分享一下 getImage() 方法的样子吗.. 我收到以下错误 - ImageView 类型中的方法 setImageResource(int) 不适用于参数 (ImageView)
  • @HarshaMV 你应该传递一个可绘制资源,而不是视图本身,它应该来自 R.drawable
  • 你不需要在 ArrayAdapter 中使用 'Items[]' - ArrayAdapter 本身已经作为 ArrayList 工作 - 使用 add 将项目放入其中并使用 get 获取它们。
【解决方案2】:
 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 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>

【讨论】:

    【解决方案3】:

    六年过去了,这仍然是某些搜索的顶部。从那以后,情况发生了很大变化。现在事实上的标准或多或少地使用 Volley 和 NetworkImageView 来为您处理繁重的工作。

    假设您已经正确设置了 Apaters、Loaders 和 ListFragments,这个official google tutorial 解释了如何使用 NetworkImageView 来加载图像。图像在后台线程中自动加载,视图在 UI 线程中更新。它甚至支持缓存。

    【讨论】:

    • Volley 比手动滚动所有代码要好得多。我们在不到一个小时的时间内就拥有了我们需要的所有功能。
    • 这与列表部分无关。
    【解决方案4】:

    这是带有不同图像的简单 ListView。首先,您必须复制不同类型的图像并将其粘贴到项目中的 res/drawable-hdpi 中。图像应为 (.png) 文件格式。 然后复制此代码。

    在 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" />
    

    创建 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>
    

    在您的活动中

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

    这是完整的代码。您可以根据需要进行更改...欢迎评论

    【讨论】:

    • 简单的适配器类在哪里?
    【解决方案5】:

    我想出了一个我称之为“BatchImageDownloader”的解决方案,效果很好。以下是如何使用它的快速摘要:

    • 保留一个全局 HashMap(最好在您的 Application 对象中) 用作可绘制对象的缓存

    • 在 List Adapter 的 getView() 方法中,使用来自 用于在列表项中填充 ImageView 的缓存。

    • 创建一个 BatchImageDownloader 实例,传入您的 ListView 适配器

    • 为每个需要获取/显示的图像调用 addUrl()

    • 完成后,调用 execute()。这会触发一个获取所有 图像,并且随着每个图像被提取并添加到缓存中,它 刷新您的 ListView(通过调用 notifyDataSetChanged())

    该方法具有以下优点:

    • 使用单个工作线程来获取所有图像,而不是为每个图像/视图使用单独的线程
    • 获取图像后,所有使用该图像的列表项都会立即更新
    • 代码不会直接访问列表项中的图像视图,而是通过在列表适配器上调用 notifyDataSetChanged() 来触发列表视图刷新,而 getView() 实现只是从缓存中拉出可绘制对象并显示它。这避免了与 ListViews 中使用的回收 View 对象相关的问题。

    这里是 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;
            }
    
        }
    
    }
    

    【讨论】:

    • Aaaaa 并且链接已更改 :(
    • Link 在 2014 年底死亡,看起来像这样。这是回路机链接:web.archive.org/web/20131030043626/http://agileyogi.com/…
    • 原始答案链接指向一些其他语言的搜索引擎。不要点击它。
    • 已编辑、删除链接并在答案中包含代码和说明
    【解决方案6】:

    要从数据库中获取数据,您可以使用SimpleCursorAdapter

    我认为您可以将SimpleCursorAdapter 直接绑定到ListView - 如果不是,您可以创建一个自定义适配器类,该类使用自定义ViewBinder 扩展SimpleCursorAdapter,覆盖setViewValue

    查看Notepad 教程,了解如何使用SimpleCursorAdapter

    【讨论】:

      【解决方案7】:

      文件名应与布局 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>
      

      【讨论】:

        【解决方案8】:

        我们需要实现两种布局。一个保存列表视图,另一个保存列表视图的行项。实现您自己的自定义适配器。想法是包含一个 textview 和一个 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; 
         }
        

        接下来,我们在主 Activity 中实现功能,以在运行时动态包含图像和文本数据。您可以将动态创建的文本数组和图像 id 数组传递给自定义适配器的构造函数。

        Customlistadapter adapter = new Customlistadapter(this, image_id, text_name);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-05-20
          相关资源
          最近更新 更多