ListView的基础应用

  在写完基础的布局之后,下一课我们会学习一下如何使用Android中一个非常重要,但是对于新手略有困难的ListView,甚至很久以前都有人说过,会不会写ListView是Android能否入门的第一步。

  好了,说了这么多,写这个教程也是希望大家能加深一下印象,提前预习,以免听沙龙的时候一头雾水。

  如上图所示的界面就是一个ListView,如名字所说,ListView就是一个列表控件,通过名为Adapter的内容填充器,对其进行填充。

  这是ListView的原理图,其中的Cursor大家不用管,Cursor涉及到了数据库的操作,主要看的一条线是从ArrayList-----》 Adapter -------》 ListView。

  从这个步骤我们可以看出,使用ListView的过程,就是从数据(Arraylist),到接收器(Apapter)再放进ListView中的。

  其中的ArrayList可以认为是可以放任意东西的一种链表使用ArrayList<对象>的方式进行存储。

 1.首先我们需要一个Item的样式,就是列表里的每一项长得是什么样的。

  

  这就是我们需要的一个样式,其中出现了一个图标,一段文本,一个可点击的框(CheckBox)。

  

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <RelativeLayout
 3     xmlns:android="http://schemas.android.com/apk/res/android"
 4     android:layout_width="match_parent"
 5     android:layout_height="wrap_content">
 6     <ImageView
 7         android:id="@+id/list_img"
 8         android:layout_margin="8dp"
 9         android:src="@mipmap/ic_launcher"
10         android:layout_width="32dp"
11         android:layout_height="32dp" />
12     <TextView
13         android:id="@+id/list_text"
14         android:singleLine="true"
15         android:text="哈哈哈哈哈哈哈哈"
16         android:layout_centerVertical="true"
17         android:layout_toRightOf="@+id/list_img"
18         android:layout_width="wrap_content"
19         android:layout_height="wrap_content" />
20     <CheckBox
21         android:layout_centerVertical="true"
22         android:layout_alignParentRight="true"
23         android:layout_gravity="right"
24         android:layout_width="wrap_content"
25         android:layout_height="wrap_content" />
26 </RelativeLayout>

 

  当然作为我们默认的一个布局样式,里面最好什么都不填充。

  2.现在我们有了一个布局了,我们需要建立一个与之相对的数据对象存入三个内容。

 1 public class ListInfo {
 2     private int list_img;
 3     private String list_text;
 4     private boolean list_click;
 5 
 6     public ListInfo(int list_img, String list_text, boolean list_click) {
 7         this.list_img = list_img;
 8         this.list_text = list_text;
 9         this.list_click = list_click;
10     }
11 
12     public int getList_img() {
13         return list_img;
14     }
15 
16     public String getList_text() {
17         return list_text;
18     }
19 
20     public boolean isList_click() {
21         return list_click;
22     }
23 }

   这个类中包含刚才视图中的三个信息,一个资源id,一个文本,一个是否点击的boolean值。

 3.最重要的接收器来了,新建一个类,继承BaseAdapter:

  继承之后会默认复写四个方法。

  

 1     @Override
 2     public int getCount() {
 3         return 0;
 4     }
 5 
 6     @Override
 7     public Object getItem(int i) {
 8         return null;
 9     }
10 
11     @Override
12     public long getItemId(int i) {
13         return 0;
14     }
15 
16     @Override
17     public View getView(int i, View view, ViewGroup viewGroup) {
18         return null;
19     }

  从名字中就能看出这些方法是用来干什么的了,getCount获得总数目,getItem返回每项的一个对象,getItemId直接返回i就好,getView获取每项的视图。

  除了这些,我们还需要两个东西,一个Context上下文用于需找View,一个ArrayList就是我们用于填充的数据了,这两个东西都要通过构造函数来实现。

  

1     private ArrayList<ListInfo> userList;
2     private Context context;

  ArrayList里面存放的对象就是我们刚才创建的那个ListInfo。

  构造函数:

    public ListAdapter(Context context, ArrayList<ListInfo> userList) {
        this.context = context;
        this.userList = userList;
    }

 

  有了这些东西我们就能修改之前的三个方法了:

    @Override
    public int getCount() {
        return userList.size();
    }

    @Override
    public Object getItem(int i) {
        return userList.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

 

 

  分别用数据的size,get的Item,还有i返回。

 4.下面最重要的就是关于getview的写法:

   我们都知道布局与数据建立连接是通过先找到布局,再填充数据的方式进行的,但是ListView有很多子项,每次都要找一个个布局再填充是一个非常消耗系统机能的方式,

所以我们使用ViewHolder的方式进行缓存布局,防止多次轮询的消耗。

  所谓的ViewHolder就是通过一个内部类来缓存布局:

  

    private class ViewHolder{
        private ImageView imageView;
        private TextView textView;
        private CheckBox checkBox;
    }

 

  这个类里包含我们一个布局所需的全部控件,一个ImageView,一个TextView,一个CheckBox,这个类作为ListAdapter的一个内部类。

  然后这是getview:

 1     @Override
 2     public View getView(int i, View view, ViewGroup viewGroup) {
 3         // 首先新建viewHolder实例,由于getView这个函数会在每个Item生成的时候都运行一次,
 4         // 所以我们用了这种写法
 5         ViewHolder viewHolder = null;
 6         // view还是null时,此时为第一次创建
 7         if(view == null){
 8             // 新建实例
 9             viewHolder = new ViewHolder();
10             // 为View添加布局,此处View是Item的View
11             view = LayoutInflater.from(context).inflate(R.layout.list_item,null);
12             // 为ViewHolder填充
13             viewHolder.imageView = (ImageView)view.findViewById(R.id.list_img);
14             viewHolder.textView = (TextView)view.findViewById(R.id.list_text);
15             viewHolder.checkBox = (CheckBox)view.findViewById(R.id.list_check);
16             // 给View设定额外的标签,可存储一个数据,我们把ViewHolder存进去
17             view.setTag(viewHolder);
18         }else {
19             // 此处已经是>=2 创建Item了
20             // 把view从tag中拿出来
21             viewHolder = (ViewHolder)view.getTag();
22         }
23         // 从ArrayList找到当前项的数据
24         ListInfo listInfo = userList.get(i);
25         // 逐个填充
26         viewHolder.imageView.setImageResource(listInfo.getList_img());
27         viewHolder.textView.setText(listInfo.getList_text());
28         viewHolder.checkBox.setChecked(listInfo.isList_click());
29         return view;
30     }

 

  注释写的已经很详细了。

5.在Activity中使用:

 布局中添加:

  

1     <ListView
2         android:id="@+id/listview"
3         android:layout_width="wrap_content"
4         android:layout_height="wrap_content"
5         />

 

  Activity中添加:

  

 1         ListView listView = (ListView)findViewById(R.id.listview);
 2 
 3         ArrayList<ListInfo> arrayList = new ArrayList<>();
 4 
 5         for(int i = 0;i < 10;i++){
 6             arrayList.add(new ListInfo(R.mipmap.ic_launcher,"蛤蛤蛤蛤",true));
 7             arrayList.add(new ListInfo(R.mipmap.ic_launcher,"蛤蛤",false));
 8         }
 9 
10         ListAdapter adapter = new ListAdapter(this,arrayList);
11 
12         listView.setAdapter(adapter);

 

  注意到新建了ArrayList然后随意new了20个子项。

  然后填充进Adapter里,然后再给ListView添加Adapter就可以了。

  

  这就是最后完成的界面了!大家试试吧!

    源码下载

posted @ 2015-12-01 13:48  刘丰恺  阅读(606)  评论(0编辑  收藏