简介:ListView组件是在Android APP开发中经常用到的组件,主要是用来显示列表以及相应按下触发完成界面的跳转。
xml文件在ListView中的使用:
xml的作用:xml文件在Android开发中往往承担了界面的布局的作用,其中包含了各个组件以及它们在界面上存储的位置;同时比如strings.xml文件可以配置activity中用到的字符串,dimens.xml文件可以配置边界的位置参数。MainActivity也有属于它的布局文件,其中ListView是其中的一个组件。xml文件类似于给具体内容的实现框定了一个格式,它规定了ListView中数据填充的形式,实现了M(模型)和V(视觉)的分离。
activity_main.xml:
<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.asynctask.MainActivity" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:textSize="30sp"
android:text="@string/title1" />
<!-- ListView 由item.xml里的TextView给值 。-->
<ListView
android:id="@+id/listView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/textView1"
/>
</RelativeLayout>
效果图:
分析:布局文件的ListView中第一行代码为它申请了唯一的id标识,第二、三行代码表示它的大小可以自适应内容的大小而变化,第四行体现了相对布局的特点,ListView放在文本textView的下方。ListView中的item的格式在哪里约束呢?同理,为其中的item自然也需要相应的xml文件来进行配置,在layout文件加下新建一个xml文件,如下:
item.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" >
<!-- 下面两个是用来给 activity_main.xml里的ListView赋值,-->
<TextView
android:id="@+id/Textviewname"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="1"
android:textSize="30sp"
/>
<TextView
android:id="@+id/Textviewage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="2"
android:textSize="30sp"
/>
</LinearLayout>
效果图:
分析:从以上效果图中可以清晰地看到它对于每个item的格式约束,使得item的内容由两个文本区域组成,他们各占一半的空间。
BaseAdapter(数据适配器)
**BaseAdapter原理:**接下来要解决的问题就是如何在数据源和用户界面的显示之间建立一个联系,如何把数据库中具体的用户信息显示在列表中。这时就需要使用到数据适配器BaseAdapter了,它个作用就是在数据和显示之间建立一个纽带,实现了数据和显示之间的解耦,符合设计模式中松耦合的设计要求。当然,这个过程会遵守上述xml文件的布局要求。代码中,我们使用一个循环生成一些user对象,模拟数据库。BaseAdapter只需要xml的布局配置信息,以及数据信息,就能动态地配置数据的显示,内部是有封装好的显示的代码的。
BaseAdapter的缓存机制:当列表中数据比较多的时候,往往需要下拉才能得到其余的列表信息,这时,如果频繁地创建新的view会造成资源的浪费也会比较低效。BaseAdapter自带缓存的功能,它维护的view包括两个部分,一部分是当前显示的,另一部分是没有被显示的,没有被显示的那个组件就是缓存区的组件。比如当item0离开显示区后,它会被先保存在缓存区,当一个新的item9准备进入显示区时,适配器会先取出那个item0,把它的数据修改为item9的数据,然后从下方开始显示,这样就形成了一种循环,节省了资源。
MainActivity:
public class MainActivity extends Activity {
private TextView tv1;//item.xml里的TextView:Textviewname
private TextView tv2;//item.xml里的TextView:Textviewage
private ListView lv;//activity_main.xml里的ListView
private BaseAdapter adapter;//要实现的类
private List<User> userList = new ArrayList<User>();//实体类
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView) findViewById(R.id.listView1);
//模拟数据库
for (int i = 0; i < 20; i++) {
User ue = new User();//给实体类赋值
ue.setName("小米"+i);
ue.setAge("18");
userList.add(ue);
}
//new一个适配器
adapter = new BaseAdapter() {
/**
* 重写获取元素数目的方法
*/
public int getCount() {
// TODO Auto-generated method stub
return userList.size();//数目
}
/**
* 获取指定位置的item
* position表示当前要显示的的第几个视图
* convertView是缓冲区的视图
* parent是当前显示的视图组
*/
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = MainActivity.this.getLayoutInflater();//用它来载入界面
View view;//组件的视图
if (convertView==null) {
view = inflater.inflate(R.layout.item, null);//缓存区没有就新建一个view
}else{
view=convertView;//缓存区存在就把它作为当前view
Log.i("info","有缓存,不需要重新生成"+position);
}
tv1 = (TextView) view.findViewById(R.id.Textviewname);//找到Textviewname组件
tv1.setText(userList.get(position).getName());//通过数据库中的数据配置组件的参数
tv2 = (TextView) view.findViewById(R.id.Textviewage);//找到Textviewage组件
tv2.setText(userList.get(position).getAge());//设置参数
return view;
}
/**
* 获取id
*/
public long getItemId(int position) {//取在列表中与指定索引对应的行id
return 0;
}
/**
* 获取item对象
*/
public Object getItem(int position) {//获取数据集中与指定索引对应的数据项
return null;
}
};
lv.setAdapter(adapter);//生效适配器
//获取当前ListView点击的行数,并且得到该数据
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
//
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
tv1 = (TextView) view.findViewById(R.id.Textviewname);//找到Textviewname
String str = tv1.getText().toString();//得到数据
Toast.makeText(MainActivity.this, "" + str, Toast.LENGTH_SHORT).show();//显示数据
Intent it = new Intent(MainActivity.this, History.class); //创建一个意图对象
Bundle b = new Bundle();//创建一个Bundle对象,用于传递数据
b.putString("we",str); //添加数据到Bundle
it.putExtras(b);//把Bundle添加到意图对象
startActivity(it);//执行这个意图
}
});
}
}
user类(承载数据信息):
class User {
private String name;
private String age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + "]";
}
}
最终效果: