原文网址:http://sunbofu.blog.51cto.com/6431507/1280441
Android中的listview目测是一个使用频率很高的组件,所以今天来总结一下listview的基础的用法。
一、最基本的绑定
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
42
43
44
45
46
47
48
49
50
51
52
53
54
|
package com.tmnw;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class MainActivity extends Activity {
/*----ListView MVC实现----*/
// model
List<String> data;
// view
ListView lv;
// controller
ArrayAdapter<String> adapter;
int size = 1 ;
// 初始化组件
private void initWidget() {
lv = (ListView) findViewById(R.id.list);
}
// 初始化绑定数据
private void initData() {
if (lv == null )
return ;
// 第一步:获取数据源(model)
data = new ArrayList<String>();
appendData();
// 第二步:new一个适配器(controller)
// 参数1:Context
// 参数2:listview的item布局
// 参数3:数据填充在item布局下的那个控件id
// 参数4:填充的数据
adapter = new ArrayAdapter<String>( this , R.layout.simple_text,
R.id.text1, data);
// 第三步:给listview设置适配器(view)
lv.setAdapter(adapter);
}
// 添加数据
private void appendData() {
if (data == null )
return ;
for ( int i = 0 ; i < 10 ; i++) {
data.add( "" + size++);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initWidget();
initData();
}
} |
(吐槽一下为神马把我代码里的空行去掉了,感觉好难看)
xml代码:
activity_main.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
< LinearLayout 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:orientation = "vertical"
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 = ".MainActivity" >
< ListView
android:id = "@+id/list"
android:layout_width = "match_parent"
android:layout_height = "0dip"
android:layout_weight = "1" >
</ ListView >
</ LinearLayout >
|
simple_text.xml
1
2
3
4
5
6
7
|
<? xml version = "1.0" encoding = "utf-8" ?>
< TextView xmlns:android = "http://schemas.android.com/apk/res/android"
android:id = "@+id/text1"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:padding = "5dp"
android:textIsSelectable = "false" />
|
画面效果:
二、给ListView添加头和尾部
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
|
// 初始化组件 private void initWidget() {
lv = (ListView) findViewById(R.id.list);
header = getLayoutInflater().inflate(R.layout.simple_text, null );
((TextView) header.findViewById(R.id.text1)).setText( "这是一个头部" );
footer = getLayoutInflater().inflate(R.layout.simple_text, null );
((TextView) footer.findViewById(R.id.text1)).setText( "加载中..." );
}
// 初始化绑定数据 private void initData() {
if (lv == null )
return ;
// 第一步:获取数据源(model)
data = new ArrayList<String>();
appendData();
// 第二步:new一个适配器(controller)
// 参数1:Context
// 参数2:listview的item布局
// 参数3:数据填充在item布局下的那个控件id
// 参数4:填充的数据
adapter = new ArrayAdapter<String>( this , R.layout.simple_text,
R.id.text1, data);
// 第三步:给listview设置适配器(view)
// addHeaderView和addFooterView一定要有一个在setAdapter之前调用,或者2个都在setAdapter之前调用
lv.addHeaderView(header);
lv.setAdapter(adapter);
// 这里的参数null是数据,false说明是不能被选中的
lv.addFooterView(footer, null , false );
// 设置尾部无分割线,头部不想要分割线同理
lv.setFooterDividersEnabled( false );
}
|
(只贴了部分修改过的代码)
画面效果:
三、给ListView添加下滑加载中的一种实现方式
因为listview要滚动,所以给它添加滚动监听,为了书写简便,我让本Activity实现了OnScrollListener
1
|
public class MainActivity extends Activity implements OnScrollListener
|
java代码:
先增加几个变量
1
2
|
Button scrollInfo; Thread currentThread; |
初始化组件代码修改下
1
2
3
4
5
6
|
lv = (ListView) findViewById(R.id.list); scrollInfo = (Button) findViewById(R.id.scroll_info);
header = getLayoutInflater().inflate(R.layout.simple_text, null );
((TextView) header.findViewById(R.id.text1)).setText( "这是一个头部" );
footer = getLayoutInflater().inflate(R.layout.simple_text, null );
((TextView) footer.findViewById(R.id.text1)).setText( "加载中..." );
|
在onCreate中添加
1
|
lv.setOnScrollListener( this );
|
实现OnScrollListener方法:
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
|
@Override public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState) {
// 手指接触屏幕滑动
case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
// 手指离开屏幕做惯性滑动
case OnScrollListener.SCROLL_STATE_FLING:
// 当滑动要最后一行时加载数据
if (view.getLastVisiblePosition() == view.getCount() - 1 ) {
// 可以通过网络加载数据等。
// 判断是否还是在加载中
if (currentThread == null || !currentThread.isAlive()) {
// 添加listview尾部控件加载中
lv.addFooterView(footer, null , false );
// 启动线程加载数据
currentThread = new DataLoadThread();
currentThread.start();
}
}
break ;
// 不滑动
case OnScrollListener.SCROLL_STATE_IDLE:
break ;
}
} @Override public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// firstVisibleItem:第一个显示的item位置
// visibleItemCount:当前显示的item个数
// totalItemCount:listview的item总个数
scrollInfo.setText( "first:" + firstVisibleItem + " visible:"
+ visibleItemCount + " total:" + totalItemCount);
} |
添加加载数据的线程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
// 模拟加载数据 class DataLoadThread extends Thread {
@Override
public void run() {
try {
Thread.sleep( 2000 );
appendData();
// 因为Android控件只能通过主线程(ui线程)更新,所以用此方法
runOnUiThread( new Runnable() {
@Override
public void run() {
// 加载完毕,移除尾部控件
lv.removeFooterView(footer);
// 当数据改变时调用此方法通知view更新
adapter.notifyDataSetChanged();
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
|
画面效果:
四、给ListView添加item点击事件
为了书写简便,我让本Activity实现了OnItemClickListener
1
2
|
public class MainActivity extends Activity implements OnScrollListener,
OnItemClickListener
|
java代码:
然后实现其方法
1
2
3
4
5
6
7
8
9
|
@Override public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Toast.makeText(
this ,
"position:" + position + " item:"
+ parent.getItemAtPosition(position).toString(),
Toast.LENGTH_LONG).show();
}
|
给listview添加监听
1
|
lv.setOnItemClickListener( this );
|
画面效果:
(模拟器出问题了使用了真机调试,没想到图片这么大,不过比模拟器快多了)
五、自定义适配器的使用
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
|
// 自定义基础适配器 class MyAdapter extends BaseAdapter {
// listview显示的个数,如果有数据源有10条,而返回5,那么lv永远只能显示5条
// 所以最好就返回数据源的条数就好了
@Override
public int getCount() {
return data.size();
}
// 获取item绑定的数据时调用
@Override
public Object getItem( int position) {
return data.get(position);
}
// itemId
@Override
public long getItemId( int position) {
return position;
}
// lv显示几个item就会调用几次此方法,然后返回一个view对象显示
// position:位置
// convertView:如果lv不能显示全部的数据,那么滚动后会把从显示到不显示的View传进来复用
@Override
public View getView( int position, View convertView, ViewGroup parent) {
View view;
if (convertView == null ) {
view = getLayoutInflater().inflate(R.layout.simple_text, null );
} else {
view = convertView;
}
TextView tv = (TextView) view.findViewById(R.id.text1);
tv.setText(data.get(position));
// 隔行变色,可以随心所欲
if ((position & 1 ) == 1 ) {
tv.setBackgroundResource(android.R.color.holo_green_light);
} else {
tv.setBackgroundResource(android.R.color.holo_red_light);
}
return view;
}
}
|
然后修改一下setAdapter()
1
2
3
|
// adapter = new ArrayAdapter<String>(this, R.layout.simple_text, // R.id.text1, data);
adapter = new MyAdapter();
|
画面效果:
(基础的到此为止,又是一个鸡肉味的周末)