一、实现效果
这是整体实现效果。
二、实现步骤
(1)实现一个简单的自定义ListView;(2)给这个ListView添加一个底部进度提示;(3)实现ListView滚动监听。
三、整个项目实现
(1)项目结构
其中ApkInfo.java是ListView Item的一个实体类,描述了Item里相关的信息。这个就不多说了,主要是get和set相关方法;
(2)看下MyAdapter.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
55
56
57
58
59
60
61
62
63
64
65
|
package
com.example.listviewdemo;
import
java.util.ArrayList;
import
android.content.Context;
import
android.view.LayoutInflater;
import
android.view.View;
import
android.view.ViewGroup;
import
android.widget.BaseAdapter;
import
android.widget.ImageView;
import
android.widget.TextView;
/**
* listView适配器
*
*
*/
public
class
MyAdapter
extends
BaseAdapter {
ArrayList<ApkInfo> apkInfos_list;
LayoutInflater inflater;
public
MyAdapter(ArrayList<ApkInfo> apkInfos_list, Context context) {
this
.apkInfos_list = apkInfos_list;
this
.inflater = LayoutInflater.from(context);
}
public
void
onDataChange(ArrayList<ApkInfo> apkInfos_list) {
this
.apkInfos_list = apkInfos_list;
this
.notifyDataSetChanged();
}
@Override
public
int
getCount() {
return
apkInfos_list.size();
}
@Override
public
Object getItem(
int
position) {
return
apkInfos_list.get(position);
}
@Override
public
long
getItemId(
int
position) {
return
position;
}
@Override
public
View getView(
int
position, View convertView, ViewGroup parent) {
ApkInfo apkInfo = apkInfos_list.get(position);
ViewHolder holder;
if
(convertView ==
null
) {
holder =
new
ViewHolder();
convertView = inflater.inflate(R.layout.item_layout,
null
);
holder.name_tv = (TextView) convertView.findViewById(R.id.item3_apkname);
holder.des_tv = (TextView) convertView.findViewById(R.id.item3_apkdes);
holder.info_tv = (TextView) convertView.findViewById(R.id.item3_apkinfo);
holder.item_iv = (ImageView) convertView.findViewById(R.id.item3_apkiv);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.name_tv.setText(apkInfo.getName());
holder.des_tv.setText(apkInfo.getDes());
holder.info_tv.setText(apkInfo.getInfo());
holder.item_iv.setImageResource(apkInfo.getImage());
return
convertView;
}
class
ViewHolder {
TextView name_tv;
TextView des_tv;
TextView info_tv;
ImageView item_iv;
}
}
|
这个Adapter是AdapterView视图与数据之间的桥梁,Adapter提供对数据的访问,也负责为每一项数据产生一个对应的View。
看看,其中ListView里的Item实现效果:
配置文件item_layout.xml的实现:
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
55
|
<?
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
=
"vertical"
>
<
LinearLayout
android:layout_width
=
"fill_parent"
android:layout_height
=
"60dip"
android:background
=
"@drawable/app_item_bg"
android:gravity
=
"center_vertical"
android:orientation
=
"horizontal"
>
<
ImageView
android:id
=
"@+id/item3_apkiv"
android:layout_width
=
"50dip"
android:layout_height
=
"50dip"
android:layout_marginLeft
=
"10dip"
/>
<
LinearLayout
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:layout_marginLeft
=
"10dip"
android:layout_weight
=
"1"
android:orientation
=
"vertical"
>
<
TextView
android:id
=
"@+id/item3_apkname"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:text
=
"应用程序名字"
android:textColor
=
"@color/black"
android:textSize
=
"18dip"
/>
<
TextView
android:id
=
"@+id/item3_apkinfo"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:layout_marginTop
=
"5dip"
android:text
=
"应用程序信息"
android:textSize
=
"14dip"
/>
</
LinearLayout
>
<
Button
android:id
=
"@+id/item3_dlbtn"
android:layout_width
=
"60dip"
android:layout_height
=
"30dip"
android:layout_marginRight
=
"10dip"
android:background
=
"@drawable/dlbtn_selector"
android:text
=
"卸载"
/>
</
LinearLayout
>
<
TextView
android:id
=
"@+id/item3_apkdes"
android:layout_width
=
"fill_parent"
android:layout_height
=
"30dip"
android:layout_marginLeft
=
"5dip"
android:layout_marginRight
=
"5dip"
android:gravity
=
"center_vertical"
android:text
=
"应用程序描述"
android:textSize
=
"14dip"
/>
</
LinearLayout
>
|
(3)自定义ListView实现
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
package
com.example.listviewdemo;
import
android.content.Context;
import
android.util.AttributeSet;
import
android.view.LayoutInflater;
import
android.view.View;
import
android.widget.AbsListView;
import
android.widget.AbsListView.OnScrollListener;
import
android.widget.ListView;
public
class
LoadListView
extends
ListView
implements
OnScrollListener {
View footer;
// 底部布局
int
totalItemCount;
// ListView加载数据总量
int
lastVisibaleItem;
// 底部显示的数据下标
boolean
isLoading;
// 是否在加载
OnLoaderListener loaderListener;
// 加载监听
public
LoadListView(Context context) {
super
(context);
initView(context);
}
public
LoadListView(Context context, AttributeSet attrs) {
super
(context, attrs);
initView(context);
}
public
LoadListView(Context context, AttributeSet attrs,
int
defStyle) {
super
(context, attrs, defStyle);
initView(context);
}
@Override
public
void
onScrollStateChanged(AbsListView view,
int
scrollState) {
/**
* scrollState = SCROLL_STATE_TOUCH_SCROLL(1) 正在滚动 ; scrollState =
* SCROLL_STATE_FLING(2) 手指做了抛的动作(手指离开屏幕前,用力滑了一下); scrollState =
* SCROLL_STATE_IDLE(0) 停止滚动 ; 当滚动到最后一行,且停止滚动,加载数据;
*/
if
(totalItemCount == lastVisibaleItem && scrollState == SCROLL_STATE_IDLE) {
if
(!isLoading) {
isLoading =
true
;
footer.findViewById(R.id.load_layout).setVisibility(View.VISIBLE);
loaderListener.onLoad();
// 加载更多
}
}
}
@Override
public
void
onScroll(AbsListView view,
int
firstVisibleItem,
int
visibleItemCount,
int
totalItemCount) {
/**
* 滚动一直回调直到停止滚动时才停止回调,单击时回调一次; 列表到达结尾之前,我们要加载数据模块;
* firstVisibleItem表示当前屏幕显示的第一个listItem在整个listView里的位置(下标从0开始);
* visibleItemCount表示当前屏幕可见的listItem(部分显示的listItem也算)总数;
* totalItemCount表示listView里listItem总数。
*/
this
.lastVisibaleItem = firstVisibleItem + visibleItemCount;
this
.totalItemCount = totalItemCount;
}
/**
* 底部进度调加载到listview
*
* @param context
*/
private
void
initView(Context context) {
LayoutInflater inflater = LayoutInflater.from(context);
footer = inflater.inflate(R.layout.footer_layout,
null
);
footer.findViewById(R.id.load_layout).setVisibility(View.GONE);
this
.addFooterView(footer);
// 加到底部
this
.setOnScrollListener(
this
);
// 监听滚动到底部
}
/**
* 加载完毕
*/
public
void
loadComplete() {
isLoading =
false
;
footer.findViewById(R.id.load_layout).setVisibility(View.GONE);
}
public
void
setLoaderListener(OnLoaderListener loaderListener) {
this
.loaderListener = loaderListener;
}
// 加载更多回调接口
public
interface
OnLoaderListener {
public
void
onLoad();
}
}
|
添加底部加载进度条
footer_layout.xml实现如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
<?
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
=
"vertical"
>
<
LinearLayout
android:id
=
"@+id/load_layout"
android:layout_width
=
"match_parent"
android:layout_height
=
"wrap_content"
android:gravity
=
"center"
android:orientation
=
"horizontal"
android:paddingBottom
=
"10dip"
android:paddingTop
=
"10dip"
>
<
ProgressBar
style
=
"?android:attr/progressBarStyleSmall"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
/>
<
TextView
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:text
=
"10条载入中..."
/>
</
LinearLayout
>
</
LinearLayout
>
|
(4)MainActivity.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
55
56
57
58
59
60
61
62
63
|
package
com.example.listviewdemo;
import
java.util.ArrayList;
import
com.example.listviewdemo.LoadListView.OnLoaderListener;
import
android.os.Bundle;
import
android.os.Handler;
import
android.app.Activity;
public
class
MainActivity
extends
Activity
implements
OnLoaderListener {
ArrayList<ApkInfo> apkInfos_list =
new
ArrayList<ApkInfo>();
MyAdapter adapter;
LoadListView listview;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getData();
showListView(apkInfos_list);
}
private
void
showListView(ArrayList<ApkInfo> apkInfos_list) {
if
(adapter ==
null
) {
listview = (LoadListView) findViewById(R.id.listview);
listview.setLoaderListener(
this
);
adapter =
new
MyAdapter(apkInfos_list,
this
);
listview.setAdapter(adapter);
}
else
{
adapter.onDataChange(apkInfos_list);
}
}
private
void
getData() {
for
(
int
i =
0
; i <
10
; i++) {
ApkInfo apkInfo =
new
ApkInfo();
apkInfo.setName(
"测试程序I"
);
apkInfo.setInfo(
"50w用户"
);
apkInfo.setDes(
"这是一个神奇的应用!"
);
apkInfo.setImage(R.drawable.ic_launcher);
apkInfos_list.add(apkInfo);
}
}
private
void
loadData() {
for
(
int
i =
0
; i <
10
; i++) {
ApkInfo apkInfo =
new
ApkInfo();
apkInfo.setName(
"测试程序II"
);
apkInfo.setInfo(
"50w用户"
);
apkInfo.setDes(
"这是一个更加神奇的应用!"
);
apkInfo.setImage(R.drawable.test_icon);
apkInfos_list.add(apkInfo);
}
}
@Override
public
void
onLoad() {
Handler handler =
new
Handler();
handler.postDelayed(
new
Runnable() {
@Override
public
void
run() {
// 获取更多数据
loadData();
// 更新listview显示;
showListView(apkInfos_list);
// 通知listview加载完毕
listview.loadComplete();
}
},
2000
);
}
}
|
activity_main.xml配置文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<
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"
tools:context
=
".MainActivity"
>
<
com.example.listviewdemo.LoadListView
android:id
=
"@+id/listview"
android:layout_width
=
"fill_parent"
android:layout_height
=
"wrap_content"
android:background
=
"@color/white"
android:cacheColorHint
=
"#00000000"
android:dividerHeight
=
"5dip"
>
</
com.example.listviewdemo.LoadListView
>
</
RelativeLayout
>
|
到这里整个实现就算完成了,这里使用了handler.postDelayed延时两秒加载只是为了实验效果。这是在慕课网上学习时的笔记,大家要想更加深入地了解相关知识,请移步慕课网吧,感觉很实用!
源码下载猛戳:http://download.csdn.net/detail/shizhao0716/8382029