ListView控件 这个控件就是一个列表框控件,比较的常见,基本每个软件都有的。
控件性质 其实这个和之前的那个下拉框和文本提示框基本上性质一样,都是控件-适配器-数据,这三个东西构成的。
简单适配器 其实这里说的简单,是指的适配器比较简单,用安卓给我们提供的适配器:android.R.layout.simple_list_item_1。 布局:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <RelativeLayout xmlns:android ="http://schemas.android.com/apk/res/android" xmlns:tools ="http://schemas.android.com/tools" android:layout_width ="match_parent" android:layout_height ="match_parent" android:paddingBottom ="@dimen/activity_vertical_margin" android:paddingLeft ="@dimen/activity_horizontal_margin" android:paddingRight ="@dimen/activity_horizontal_margin" android:paddingTop ="@dimen/activity_vertical_margin" tools:context ="com.example.android_study9.MainActivity" > <ListView android:id ="@+id/Lv" android:layout_width ="match_parent" android:layout_height ="match_parent" > </ListView > </RelativeLayout >
布局的话呢就是一个列表框。 代码实现方面的话呢,也是比较简单的。
1 2 3 4 5 6 7 8 9 10 11 final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this , android.R.layout.simple_list_item_1,getData());Lv.setAdapter(adapter); private String[] getData(){ return new String[]{"a" ,"b" ,"c" ,"d" }; }
自定义适配器 这个是我们比较关注的,因为功能强大而且漂亮。
首先我们需要一个布局:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android ="http://schemas.android.com/apk/res/android" android:layout_width ="wrap_content" android:layout_height ="wrap_content" > <ImageView android:id ="@+id/iv_ava" android:layout_width ="40dip" android:layout_height ="40dip" android:src ="@drawable/ic_launcher" /> <TextView android:id ="@+id/tx_name" android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:text ="Wker" android:layout_toRightOf ="@+id/iv_ava" android:layout_centerVertical ="true" android:layout_marginLeft ="70dip" /> <TextView android:id ="@+id/tx_des" android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:text ="最帅的男人" android:layout_centerVertical ="true" android:layout_toRightOf ="@+id/tx_name" /> </RelativeLayout >
这个时候我们需要给他们ID,因为我们需要在后面用到。 主布局的话呢和简单的是一样的。
然后因为我们是自定义的适配器,所以我们需要自己设置一个继承于适配器的一个类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 package com.example.android_study9.adapter;import java.util.List;import com.example.android_study9.R;import com.example.android_study9.model.finendmodel;import android.content.Context;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.TextView;public class FriendsAdapter extends BaseAdapter { public List<finendmodel> mData; private Context ctx; public FriendsAdapter (Context ctx,List<finendmodel> mData) { this .ctx = ctx; this .mData = mData; } @Override public int getCount () { return mData.size(); } @Override public Object getItem (int arg0) { return mData.get(arg0); } @Override public long getItemId (int arg0) { return arg0; } @Override public View getView (int arg0, View arg1, ViewGroup arg2) { View v = arg1; holder h = null ; if (v == null ) { v = View.inflate(ctx, R.layout.picture, null ); h = new holder(); h.iv_ava = (ImageView) v.findViewById(R.id.iv_ava); h.tx_name = (TextView) v.findViewById(R.id.tx_name); h.tx_des = (TextView) v.findViewById(R.id.tx_des); v.setTag(h); }else { h = (holder) v.getTag(); } finendmodel f = mData.get(arg0); h.iv_ava.setImageResource(f.getImgId()); h.tx_name.setText(f.getName()); h.tx_des.setText(f.getDes()); return v; } private static class holder { private ImageView iv_ava; private TextView tx_name; private TextView tx_des; } }
说难的话呢也不是很难,但也不算是简单,首先构造方法中需要传递一个设备上下文,需要一个List的泛型数据,这个泛型的类是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package com.example.android_study9.model;public class finendmodel { private int imgId; private String name; private String des; public int getImgId () { return imgId; } public void setImgId (int imgId) { this .imgId = imgId; } public String getName () { return name; } public void setName (String name) { this .name = name; } public String getDes () { return des; } public void setDes (String des) { this .des = des; } }
主要是用来存储我们的图片ID,名称和说明的。 getCount的话呢返回我们的List的个数,也就是我们的项目数目,getItem的话呢就是返回当前这个项目的数据,getItemId的话呢就是返回Item的ID,其实也及时把他的参数返回回去就好了(一般是),最关键的就是getView这个方法。 首先我们先是构造了一个内部类,这个内部类是静态的,目的是为了能够更好的释放内存,类里面存储了我们需要用到的数据,在我们的getView中,我们需要返回当前Item项目的一个View视图,这个视图我们通过: View.inflate(ctx, R.layout.picture, null);
来获取,第二个参数,是我们自定义的一个布局。 然后我们new了一个我们的内部类,用于存储对应的控件,然后设置标签给这个View,为什么要这么做呢?因为我们如果每加载一个项目,都要加载布局,然后找控件,占用的资源太多了,而且速度慢,这个时候安卓提供给我们一个缓存机制,也就是参数传递给我们的View arg1
,如果这个不为null,就是当前项目的一个缓存,这个时候我们只需要判断是不是为null,不是的话呢就用之前的这个项目,那么我们的内存就会比较的快了,为什么可以这样,因为我们缓存的也就是当我们往下滑动,看不到的那部分丢弃的,这个时候,再通过这个内部类,我们就可以实现一个减少内存的一个效果了,然后我们设置空间属性,最后将我们的View返回回去。 构造完毕这个类之后我们编写主窗体:
1 2 3 mAdapter = new FriendsAdapter(this , getData1()); Lv = (ListView) findViewById(R.id.Lv); Lv.setAdapter(mAdapter);
getData就是用来返回数据的。
1 2 3 4 5 6 7 8 9 10 11 12 private List<finendmodel> getData1 () { List<finendmodel> list = new ArrayList<finendmodel>(); for (int i = 0 ; i < 20 ; i++) { finendmodel f = new finendmodel(); f.setDes("Wker" +i); f.setName("Wker" +i+i); f.setImgId(R.drawable.ic_launcher); list.add(f); } return list; }
其实也就是返回回去一个finendmodel泛型的List集合,然后我们可以增加两个点击事件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Lv.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick (AdapterView<?> arg0, View arg1, int arg2, long arg3) { String txt = ((finendmodel)mAdapter.getItem(arg2)).getName(); Toast.makeText(MainActivity.this , txt, Toast.LENGTH_SHORT).show();; } }); Lv.setOnItemLongClickListener(new OnItemLongClickListener() { @Override public boolean onItemLongClick (AdapterView<?> arg0, View arg1, int arg2, long arg3) { String txt = ((finendmodel)mAdapter.getItem(arg2)).getDes(); Toast.makeText(MainActivity.this , txt, Toast.LENGTH_SHORT).show(); return true ; } });
看名字就知道了,第一个是单击,第二个是长按,需要注意的是长按的返回值决定了是否允许点击事件。mAdapter.getItem(arg2)
这个getItem方法使我们自己重写的,返回的也就是项目,以为我们知道这个返回来的就是一个finendmodel,我们可以强转,然后再从里面获取数据就好了。