通过SimpleAdapter直接在ListView中显示图片

来源:互联网 发布:js车牌代表什么意思 编辑:程序博客网 时间:2024/05/16 19:05

最近在做一个界面,想法是把一个目录中的图片显示在一个GridView控件中,做成类似
缩略图的效果。


我们知道GridView和ListView都是AbsListView的子类。实现GridView和ListView最关键
的步骤就是给它们设定Adapter。一般有三种方法:用ArrayAdapter,用SimpleAdapter,
或者自定义一个BaseAdapter的子类。由于我们显示的项是图片,所以用ArrayAdapter不
合适,我们选择SimpleAdapter。


SimpleAdapter名叫Simple,其实功能很强大,它可以支持每一项包含很多组件。它的构
造器为
SimpleAdapter(Context context, 
List<? extends Map<String, ?>> data, 
int resource, 
String[] from, 
int[] to)


其中Context一般是要构造的ListView类所在的Activity类;
data是一个List,该List的每一项都是一个Map,Map里每一个String类型的Key值与第四
个参数from的元素一致,对应一个数据项;有N个列表项,List的长度就是N;
resource是列表项的布局文件,用于描述列表项的外观;
from对应第二个参数data中Map的Key值;
to对应第三个参数resource布局文件中的组件id,这些组件依次由data中Map的各项来填
充;Map中有M项,from就有M个Key值,to就有M个组件id,这些都是一一对应的。


SimpleAdapter的典型用法是:

/**************GridViewTestActivity****************************/GridView gridview=(GridView)findViewById(R.id.grid_view);String[] names=new String[]{"name1","name2","name3"};int[] imageIds=new int[]{R.drawable.img1,R.drawable.img2,R.drawable.img3};String[] keys=new String[]{"name","image"};List<Map<String,Object>> list=new List<Map<String,Object>>();for(int i=0;i<names.length;i++){Map<String,Object> map=new Hashmap<String,Object>();map.put(key[0],names[i]);map.put(key[1],images[i];list.add(map);}gridView.setAdaper(new SimpleAdapter(this,list,R.layout.list_item,keys,new int[]{R.id.textview,R.id.imageview});<!---------------/layout/list_item.xml-----------><LinearLayout><TextView android:id="@+id/textview"/><ImageView android:id="@+id/imageview"/><LinearLayout>


上面这种用法的前提是,要填充的图片数据是以本地资源的形式存在的,因此可以直接
提供资源id;但如果像我今天这种用法,我需要把一个文件夹下的图片作为数据源填充
到列表项中,这种方法就行不通了。


解决的办法是给SimpleAdapter指定一个新的ViewBinder。
查看SimpleAdapter的源码我们可以看到,getView方法调用了createViewFromResource
方法,而后者又调用了bindView方法,在bindView方法中有以下代码

for (int i = 0; i < count; i++) {            final View v = view.findViewById(to[i]);            if (v != null) {                final Object data = dataSet.get(from[i]);                String text = data == null ? "" : data.toString();                if (text == null) {                    text = "";                }                boolean bound = false;                if (binder != null) {                    bound = binder.setViewValue(v, data, text);                }                if (!bound) {                    if (v instanceof Checkable) {                        if (data instanceof Boolean) {                            ((Checkable) v).setChecked((Boolean) data);                        } else if (v instanceof TextView) {                            // Note: keep the instanceof TextView check at the bottom of these                            // ifs since a lot of views are TextViews (e.g. CheckBoxes).                            setViewText((TextView) v, text);                        } else {                            throw new IllegalStateException(v.getClass().getName() +                                    " should be bound to a Boolean, not a " +                                    (data == null ? "<unknown type>" : data.getClass()));                        }                    } else if (v instanceof TextView) {                        // Note: keep the instanceof TextView check at the bottom of these                        // ifs since a lot of views are TextViews (e.g. CheckBoxes).                        setViewText((TextView) v, text);                    } else if (v instanceof ImageView) {                        if (data instanceof Integer) {                            setViewImage((ImageView) v, (Integer) data); //1                                                  } else {                            setViewImage((ImageView) v, text);                        }                    } else {                        throw new IllegalStateException(v.getClass().getName() + " is not a " +                                " view that can be bounds by this SimpleAdapter");                    }                }            }        }


我们看到,先用ViewBinder的setViewValue来设置各个View组件,如果设置成功,返回true;如果没有设置成功,返回false,然后对TextView,ImageView等分别进行处理。默认情况下,ViewBinder是不会对ImageView进行处理的,因此对ImageView的处理依赖于上述代码1处的方法。如果我们给SimpleAdapter指定一个ViewBinder,对ImageView进行处理,就可以改变SimpleAdapter的行为方式,给ImageView传递一个Bitmap而不是一个资源id,代码如下

adapter.setViewBinder(new ViewBinder(){            @Override          public boolean setViewValue(View view, Object data,                  String textRepresentation) {              if( (view instanceof ImageView) & (data instanceof Bitmap) ) {                  ImageView iv = (ImageView) view;                  Bitmap bm = (Bitmap) data;                  iv.setImageBitmap(bm);                  return true;                  }                  return false;            }               }); 

setViewValue方法中,我们做了判断,对于类型为ImageView的View,我们专门处理,用
传进来的data给它设定了一个Bitmap,并返回true,表示我们对该组件已经处理过了;
对于其他类型的View,我们简单地返回false,交由SimpleAdapter按默认方式来处理。
新建SimpleAdapter的方法和前面的一样,只是这一句
int[] imageIds=new int[]{R.drawable.img1,R.drawable.img2,R.drawable.img3};
改成了
Bitmap[] bitmaps;
.......//填充bitmaps数组的代码


总结,通过ViewBinder,我们改变了SimpleAdapter的ImageView的数据使用方式,使用
Bitmap作为数据源,取代了原来指定资源id的方式,提高了SimpleAdapter的灵活性。




0 0
原创粉丝点击