上图先
程序运行之后,显示了一个列表,这个列表的每一个条目都包含了人的姓名,性别,年龄,另外还有两个按钮,传统的listview只能显示单行的文字,这里我们用到的是自定义的listview。
要使用这样子的listview,我们就要使用自定义的adapter,也就是适配器,这个adapter需要继承自BaseAdapter,也就是
public class ItemAdapter extends BaseAdapter
之后将adapter适配到listview上,
listViewMain.setAdapter(adapter);
这是最核心的部分,首先看工程目录:
1,,Person.java
首先,我们既然是显示一个人的信息,那么就需要一个类来代表一个人,代码如下:
package com.example.listviewdemo;
public class Person {
private int age;
private String name;
private String sex;
public Person() {}
public Person(int age, String name, String sex) {
this.age = age;
this.name = name;
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String toString() {
return "Person [age=" + age + ", name=" + name + ", sex=" + sex + "]";
}
}
里面定义了三个成员变量age, name, 和sex而已。
2,ItemViewHolder,这个东西,顾名思义,也就是item中用来hold住view的东西,我们先看图
理解下,所以我们需要写一个布局文件,来装进这些view。
首先看listitem.xml的代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="@+id/line_one"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:id="@+id/item_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="20sp" />
<TextView
android:id="@+id/item_age"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="20sp" />
<TextView
android:id="@+id/item_sex"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="20sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/line_second"
android:orientation="horizontal"
android:layout_below="@id/line_one"
>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/seeStr"
android:id="@+id/seeBt"
/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/editStr"
android:id="@+id/editBt"
/>
</LinearLayout>
</RelativeLayout>
代码比较长,其实就是两个linearLayout,第一个放了三个1比1比1的TextView,第二个放了两个1比1的Button,在这里,我们可以自由的设置布局,记住给控件加上id。
怎么样获取这些东西呢,看ItemViewHolder.java
package com.example.listviewdemo;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class ItemViewHolder {
//all Buttons and TextViews is private
//using getter method to get these Buttons and TextViews
private TextView nameTv, sexTv, ageTv;
private Button seeBt, editBt;
private View parent;
public ItemViewHolder(View parent) {
this.parent = parent;
}
public Button getSeeBt() {
if (seeBt == null) {
seeBt = (Button) parent.findViewById(R.id.seeBt);
}
return seeBt;
}
public Button getEditBt() {
if (editBt == null) {
editBt = (Button) parent.findViewById(R.id.editBt);
}
return editBt;
}
public TextView getNameTv() {
if (nameTv == null) {
nameTv = (TextView) parent.findViewById(R.id.item_name);
}
return nameTv;
}
public TextView getSexTv() {
if (sexTv == null) {
sexTv = (TextView) parent.findViewById(R.id.item_sex);
}
return sexTv;
}
public TextView getAgeTv() {
if (ageTv == null) {
ageTv = (TextView) parent.findViewById(R.id.item_age);
}
return ageTv;
}
public View getParent() {
return parent;
}
}
其实也蛮简单的对吧。
因为将控件都设置成私有的变量了,所以要写一个getter函数来获取,重要的一点是,findViewById的时候,是parent来find的,那么parent是怎么来的,通过构造方法传进来的,那么我们看adapter。
adapter继承自BaseAdapter,继承它必须覆写四个方法:
@Override
public int getCount() {
return 0;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return null;
}
既然是一个listview的adapter,那么装进去的就是一条一条的数据了,也就是我们常见的集合,这里用链表,也就是List。
在这里可以表示成List<Item>
所以,以上四个方法,根据名字能理解一些意思了,我们看具体实现:
ItemAdapter类:
package com.example.listviewdemo;
import java.util.List;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
public class ItemAdapter extends BaseAdapter {
private List<Person> personList;
private Context context;
// 用以加载布局的布局加载器
private LayoutInflater inflater;
// 构造函数
public ItemAdapter(Context context) {
this.context = context;
// 初始化布局加载器
this.inflater = LayoutInflater.from(context);
}
// getter
public List<Person> getPersonList() {
return personList;
}
// setter,设置这个adapter的数据
// 这里表示adapter装载的数据是一个装有很多Person对象的List
public void setPersonList(List<Person> personList) {
this.personList = personList;
}
// 以下四个是覆写自父类的函数
@Override
public int getCount() {
return personList.size();// 返回一共多少条数据
}
@Override
public Person getItem(int pos) {
return personList.get(pos);// 返回指定位置的item
}
@Override
public long getItemId(int arg0) {
return 0;
}
// 这是最为关键的一个函数,将数据显示在listview中
@Override
public View getView(int pos, View convertView, ViewGroup vg) {
ItemViewHolder holder;
if (convertView == null) {
holder = new ItemViewHolder(inflater.inflate(R.layout.listitem,
null));
convertView = holder.getParent();
convertView.setTag(holder);
} else {
holder = (ItemViewHolder) convertView.getTag();
}
Person p = personList.get(pos);
holder.getNameTv().setText(p.getName());
holder.getSexTv().setText(p.getSex());
holder.getAgeTv().setText(p.getAge() + "");
return convertView;
}
}
getView方法中涉及到Android加载listview的机制,参考这篇文章的后半部分:http://www.cnblogs.com/noTice520/archive/2011/12/05/2276379.html
最后看MainActivity:
package com.example.listviewdemo;
import java.util.ArrayList;
import java.util.List;
import android.os.Bundle;
import android.app.Activity;
import android.widget.ListView;
public class MainActivity extends Activity {
private ListView listViewMain;
private ItemAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listViewMain = (ListView) findViewById(R.id.main_lv);
adapter = new ItemAdapter(MainActivity.this);//new 一个适配器
adapter.setPersonList(getRes());//设置数据
listViewMain.setAdapter(adapter);//设置适配器
}
//本来应该做的是从数据库中取到相应的数据,这里为了简单,直接获取一个list。
private List<Person> getRes() {
List<Person> personList = new ArrayList<Person>();
Person p1 = new Person(18, "granton", "boy");
personList.add(p1);
Person p2 = new Person(18, "zhuang", "boy");
personList.add(p2);
Person p3 = new Person(18, "zhangsan", "boy");
personList.add(p3);
Person p4 = new Person(18, "lisi", "girl");
personList.add(p4);
Person p5 = new Person(18, "wangwu", "girl");
personList.add(p5);
Person p6 = new Person(18, "aaaaa", "girl");
personList.add(p6);
return personList;
}
}
MainActivity就很简单啦,这里没有设置点击监听,长按监听之类的事件,这些监听和普通的listview是一样的。
最后附上MainActivity的布局文件
<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:padding="10dp"
tools:context=".MainActivity" >
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/main_lv"
></ListView>
</RelativeLayout>
------granton------