Adapter类One之ListView

今天要学习的这个adapter灰常重要,也是UI组件的一个难点

adapter:适配器,是适配器视图与数据之间的桥梁

简单地可以这样理解:将各种数据以合适的形式显示到view上,提供给用户看。

这里的话先说下MVC这种程序框架:

举例:大型的商业程序通常由多人一同开发完成,比如有人负责操作接口的规划与设计,有人负责程序代码的编写

如果要能够做到程序项目的分工就必须在程序的结构上做适合的安排,如果,接口设计与修改都涉及到程序代码的改变的话,

那么两者的分工就会造成执行上的困难

良好的程序架构师将整个程序项目划分为如图的三个部分:

model:通常可以理解为数据,负责执行程序的核心运算与判断逻辑,通过view获得用户输入的数据,然后根据从数据库查询相关的信息,最后进行运算和判断,再将得到的结果交给view来显示

view:用户的操作接口,说白了就是GUI,应该使用哪种接口组件,组件间的排列位置与顺序都需要设计

Controller:控制器,作为model与view之间的枢纽,负责控制程序的执行流程以及对象之间的一个互动

在adapter这里的话就是model(数据)—>controller(以什么方式显示到)—>view(用户界面)

我们的adapter就是属于controller这个部分的

adapter与其子类关系图:

ListView列表视图

以垂直列表的形式列出需要显示的列表项,eg:系统设置项与功能内容列表等

两种添加ListView到屏幕中的方法:直接使用Listview创建和让activity继承ListActivity实现

一.直接在xml中创建ListView

步骤一:

在res\values目录中创建一个数组资源的xml文件:arrays.xml:

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="utf-8"?>  
<resources>
<string-array name="myarray">
<item>语文</item>
<item>数学</item>
<item>英语</item>
<item>物理</item>
<item>化学</item>
<item>生物</item>
</string-array>
</resources>

接着,在布局文件中添加一个ListView,并使用myarray为其设置列表项

1
2
3
4
5
6
<ListView  
android:id="@id/android:list"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:entries="@array/myarray"
/>

这里的话,如果只有一个listview时,可以引用系统ListView的ID,该id的定义,必须引用系统资源中ID为list的组件,否则会报错
也可以创建一个新的id

运行后的效果图:

使用列表视图时,如何设置选项内容显得格外重要,如果没有在布局文件中通过entries指定要显示的列表项的话,可以为其设置adapter来指定需要显示的列表项,步骤有两个:

1)创建adapter对象:如果是纯文本的话通常使用arrayAdapter对象,而创建arrayAdapter对象的话可以是通过数组资源文件中创建,也可以通过Java文件中的字符串数组进行创建

2)将创建好的适配器对象与adapter进行关联:listView.setAdapter(adapter);

代码:

首先对main.xml文件进行修改,为其设置分隔条背景与宽度

1
2
3
4
5
6
7
8
9
<ListView  
android:id="@+id/listView1"
android:divider="@drawable/butbg"
android:dividerHeight="3px"
android:footerDividersEnabled="true"
android:headerDividersEnabled="true"
android:layout_height="wrap_content"
android:layout_width="match_parent"
/>

代码解释:

divider:设置分隔条,可以用颜色分割,也可以用drawable资源分割

dividerHeight:设置分隔条的高度

footerDividersEnabled:是否在footerView(表尾)前绘制一个分隔条,默认为true

headerDividersEnabled:是否在headerView(表尾)前绘制一个分隔条,默认为true

Java代码部分:

步骤:实例化一个listView,添加headerView与footerView

创建一个适配器adapter,listview.setAdapet为这个适配器添加一个某项被选中的监听器

代码:

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
package com.jay.demo;  

import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Toast;
import android.R.anim;
import android.app.Activity;

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//实例化listview,添加headView(表头),括号中的参数是一个图像对象
final ListView listView = (ListView) findViewById(R.id.listView1);
listView.addHeaderView(line());
//定义一个适配器adapter
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.myarray,android.R.layout.simple_list_item_multiple_choice);
//将适配器与listview相关联
listView.setAdapter(adapter);
listView.addFooterView(line());

listView.setOnItemClickListener(new OnItemClickListener() {

@Override
public void onItemClick(AdapterView<?> parent, View arg1, int pos, long id) {
String result = parent.getItemAtPosition(pos).toString();
Toast.makeText(getApplicationContext(), result, Toast.LENGTH_LONG).show();
}
});
}

private View line() {
ImageView image = new ImageView(this);
image.setImageResource(R.drawable.butbg);
return image;
}
}

运行截图:

代码分析:

ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.myarray,android.R.layout.simple_list_item_multiple_choice);

这句代码创建了一个ArrayAdapter类型的适配器adapter

createFromResource方法中的参数依次为:上下文,字符串数组,以及ListView的外观形式

通常的外观形式有以下几种:

simple_list_item_1:单独一行的文本框

simple_list_item_2:两个文本框组成

simple_list_item_checked:每项都是由一个已选中的列表项

simple_list_item_multiple_choice:都带有一个复选框

simple_list_item_single_choice:都带有一个单选钮

二.让Activity继承ListActivity实现:

如果我们需要的仅仅是显示一个列表的话,直接继承ListActivity类,删掉设置布局的代码,setListAdapter即可:

代码:

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
package com.jay.demo;  

import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Toast;
import android.R.anim;
import android.app.Activity;
import android.app.ListActivity;

public class MainActivity extends ListActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

String[] array = new String[]{"语文","数学","英语"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,array);
setListAdapter(adapter);
}

@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
// TODO Auto-generated method stub
super.onListItemClick(l, v, position, id);
String result = l.getItemAtPosition(position).toString();
Toast.makeText(getApplicationContext(), result, Toast.LENGTH_LONG).show();
}
}

运行截图:

代码解释:

继承ListActivity,新建一个ArrayAdapter对象,参数依次是上下文,显示形式,字符串数组,setListAdapter即可

重写onListItemClick()方法

三.使用实例

模仿QQ好友的显示栏:

前面的话我们都是用的ArrayAdapter,很简单,接下来这里的话就要使用另一个adapter了:

SimpleAdapter:功能强大,一点都不简单哦,虽然simple是简单的意思

好吧,废话不多说:一步步实现吧:

step 1:

先定义一个空的ListView

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

step 2:接着我们定义一个界面布局,作为ListView的列表项组件:

一个图片和两个textView

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
<?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" >

<!-- 定义一个用于显示头像的ImageView -->
<ImageView
android:baselineAlignBottom="true"
android:id="@+id/imgtou"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="8dp"
/>

<!-- 定义一个竖直方向的LinearLayout,把QQ呢称与说说的文本框设置出来 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:paddingLeft="8dp"
android:textColor="#1D1D1C"
/>
<TextView
android:id="@+id/says"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="13sp"
android:paddingLeft="8px"
android:textColor="#B4B4B9"
/>

</LinearLayout>

</LinearLayout>

step 3:有了Listview装列表项,也有了ListView的显示布局,还差什么呢?

就差列表项了,这里我们使用simpleAdapter来提供列表项

java部分代码:

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
package com.jay.demo;  

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.os.Bundle;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.app.Activity;


public class MainActivity extends Activity {

private String[] names = new String[]{"萌妹子","小熊猫","蒙奇-D 路飞"};
private String[] says = new String[]{"我就是个喜欢卖萌的小妮子","最讨厌拍照什么的...","我是要成为海贼王的男人"};
private int[] imgIds = new int[]{R.drawable.tou1,R.drawable.tou2,R.drawable.tou3};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);


List<Map<String, Object>> listitem = new ArrayList<Map<String,Object>>();
for(int i = 0;i < names.length; i++)
{
Map<String, Object> showitem = new HashMap<String, Object>();
showitem.put("touxiang", imgIds[i]);
showitem.put("name", names[i]);
showitem.put("says", says[i]);
listitem.add(showitem);
}

//创建一个simpleAdapter
SimpleAdapter myAdapter = new SimpleAdapter(getApplicationContext(), listitem, R.layout.simple_layout, new String[]{"touxiang","name","says"}, new int[]{R.id.imgtou,R.id.name,R.id.says});
ListView listView = (ListView) findViewById(R.id.listView1);
listView.setAdapter(myAdapter);
}
}

代码解释:

1.定义了三个资源数组,头像,QQ呢称,说说

2.定义一个存储Map集合的List集合

3.通过循环依次将资源数组中的值按对应的键存入map集合中

4.将每次的Map集合添加到定义好的List集合中

5.创建一个SimpleAdapter,构造方法中的参数分别为:

①上下文对象,

②列表项(数据),

③指定列表项的显示布局的id

④根据字符串数组中的值为键,取出Map数组中的值来生成列表项

⑤对应Map集合中的值,依次填充的布局中的组件的id

6.为ListView设置一个适配器:listView.setAdapter(myAdapter);

就这样,很简单吧!!!!

运行截图:

最后的话当然还要弄下事件监听啦

有两种:用户点击某个项,或者选择某个列表项

对应方法setOnItemClickListener()方法和setOnItemSelectedListener();

这里笔者演示的是第一种事件监听机制,另一种也一样:

代码:

1
2
3
4
5
6
7
8
listView.setOnItemClickListener(new OnItemClickListener() {  

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String show = names[position]+" 发表了说说: "+says[position];
Toast.makeText(MainActivity.this,show, Toast.LENGTH_LONG).show();
}
});

运行截图:


android 自定义adapter怎样控制listView 条数

1
2
3
4
5
@Override
public int getCount() {
// TODO Auto-generated method stub
return 3; //只显示listview的前3条
}