




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】自定义listview,支持上拉下拉刷新,自带demo.
这个博客好想不能提供下载代码啊,我只能把代码贴出来了...其实你只需看用法,不用关心具体实现,demo非常容易看懂public
class
CustomListViewActivity
extends
Activity
{
private
CustomListView
listview;
private
ArrayList<String>
data;
private
BaseAdapter
adapter;
/**
Called
when
the
activity
is
first
created.
*/
@Override
public
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
init();
setListener();
}
private
void
init(){
data
=
new
ArrayList<String>();
//虚拟一些数据
data.add("a");
data.add("b");
data.add("c");
data.add("e");
data.add("f");
data.add("g");
data.add("h");
data.add("i");
data.add("j");
data.add("k");
data.add("L");
data.add("M");
data.add("L");
data.add("N");
data.add("O");
data.add("P");
data.add("Q");
listview
=
(CustomListView)
findViewById(R.id.listview);
adapter
=
new
BaseAdapter(){
@Override
public
int
getCount()
{
return
data.size();
}
@Override
public
Object
getItem(int
position)
{
return
null;
}
@Override
public
long
getItemId(int
position)
{
return
position;
}
@Override
public
View
getView(int
position,
View
convertView,
ViewGroup
parent)
{
TextView
textView
=
new
TextView(getApplicationContext());
textView.setHeight(100);
textView.setTextSize(20);
textView.setGravity(Gravity.CENTER);
textView.setBackgroundColor(0x66666666);
textView.setTextColor(0xaaffffff);
textView.setText(data.get(position));
return
textView;
}
};
listview.setAdapter(adapter);
}
private
void
setListener(){
listview.setOnRefreshListner(new
OnRefreshListner()
{
@Override
public
void
onRefresh()
{
new
AsyncTask<Void,
Void,
ArrayList<String>>(){
@Override
protected
ArrayList<String>
doInBackground(Void...
params)
{
try
{
//模拟从服务器获取数据的过程
Thread.sleep(1500);
}
catch
(InterruptedException
e)
{
e.printStackTrace();
}
ArrayList<String>
virtualData
=
new
ArrayList<String>();
virtualData.add("Head刷新后的新数据1");
virtualData.add("Head刷新后的新数据2");
virtualData.add("Head刷新后的新数据3");
virtualData.add("Head刷新后的新数据4");
virtualData.add("Head刷新后的新数据5");
virtualData.add("Head刷新后的新数据6");
return
virtualData;
}
//更新UI的方法,系统自动实现
@Override
protected
void
onPostExecute(ArrayList<String>
result)
{
data.addAll(0,result);//注意是往前添加数据
adapter.notifyDataSetChanged();
listview.onRefreshComplete();//完成下拉刷新,这个方法要调用
super.onPostExecute(result);
}
}.execute();
}
});
//创建FootView
final
View
footer
=
View.inflate(CustomListViewActivity.this,
R.layout.footer,
null);
listview.setOnAddFootListener(new
OnAddFootListener()
{
@Override
public
void
addFoot()
{
listview.addFooterView(footer);
}
});
listview.setOnFootLoadingListener(new
OnFootLoadingListener()
{
@Override
public
void
onFootLoading()
{
new
AsyncTask<Void,
Void,
ArrayList<String>>(){
@Override
protected
ArrayList<String>
doInBackground(Void...
params)
{
try
{
//模拟从服务器获取数据的过程
Thread.sleep(2000);
}
catch
(InterruptedException
e)
{
e.printStackTrace();
}
ArrayList<String>
virtualData
=
new
ArrayList<String>();
virtualData.add("Foot刷新后的新数据1");
virtualData.add("Foot刷新后的新数据2");
virtualData.add("Foot刷新后的新数据3");
virtualData.add("Foot刷新后的新数据4");
virtualData.add("Foot刷新后的新数据5");
virtualData.add("Foot刷新后的新数据6");
return
virtualData;
}
//在doInBackground后面执行
@Override
protected
void
onPostExecute(ArrayList<String>
result)
{
data.addAll(result);//这个是往后添加数据
adapter.notifyDataSetChanged();
listview.onFootLoadingComplete();//完成上拉刷新,就是底部加载完毕,这个方法要调用
//移除footer,这个动作不能少
listview.removeFooterView(footer);
super.onPostExecute(result);
}
}.execute();
}
});
}
}下面上listview的代码,有点长.../**
*
支持下拉刷新和上拉刷新
*
可自定义上啦和下拉过程的操作,推荐使用AsyncTask
*
需自定义Foot的View,然后只需在addFoot方法中添加即可
*
@author
lxj
*
*/
public
class
CustomListView
extends
ListView
implements
OnScrollListener
{
private
static
final
int
DONE
=
0;
private
static
final
int
PULL_TO_REFRESH
=
1;
private
static
final
int
RELEASE_TO_REFRESH
=
2;
private
static
final
int
REFRESHING
=
3;
private
static
final
float
RATIO
=
3;//
用来设置实际间距和上边距之间的比例
private
int
state;//
当前下拉刷新的状态
private
int
firstVisibleIndex;//
在listview中第一个可以看见的item
private
View
headView;
private
ImageView
headArrow;
private
ProgressBar
progressBar;
private
TextView
headTitle;
private
TextView
headLastUpdate;
private
int
headContentWidth;
private
int
headContentHeight;
private
Animation
animation;
private
Animation
reverseAnimation;
private
OnRefreshListner
refreshListner;//
刷新监听器
private
boolean
isRefreshable;
private
boolean
isRecored
=
false;//
用来记录第一次按下坐标点,在整个滑动的过程中
只记录一次
private
float
startY;
private
boolean
isBack
=
false;//
是从
松开刷新状态
来到的
下拉刷新状态
public
CustomListView(Context
context,
AttributeSet
attrs)
{
super(context,
attrs);
init(context);
}
private
void
init(Context
context)
{
//
listview
设置滑动时缓冲背景色
setCacheColorHint(0x00000000);
headView
=
View.inflate(context,
R.layout.head,
null);
headArrow
=
(ImageView)
headView.findViewById(R.id.head_arrow);
progressBar
=
(ProgressBar)
headView.findViewById(R.gressbar);
headTitle
=
(TextView)
headView.findViewById(R.id.head_title);
headLastUpdate
=
(TextView)
headView
.findViewById(R.id.head_last_update);
headArrow.setMinimumWidth(50);
headArrow.setMinimumHeight(70);
MeasureView(headView);
headContentWidth
=
headView.getMeasuredWidth();
headContentHeight
=
headView.getMeasuredHeight();
headView.setPadding(0,
-1*headContentHeight,
0,
0);
//
为listView加入顶部View
addHeaderView(headView);
setOnScrollListener(this);
animation
=
new
RotateAnimation(-180,
0,
Animation.RELATIVE_TO_SELF,
0.5f,
Animation.RELATIVE_TO_SELF,
0.5f);
animation.setDuration(250);
animation.setFillAfter(true);//
设定动画结束时,停留在动画结束位置
(保留动画效果)
animation.setInterpolator(new
LinearInterpolator());//
匀速变化
reverseAnimation
=
new
RotateAnimation(0,
-180,
Animation.RELATIVE_TO_SELF,
0.5f,
Animation.RELATIVE_TO_SELF,
0.5f);
reverseAnimation.setDuration(200);
reverseAnimation.setFillAfter(true);//
设定动画结束时,停留在动画结束位置
(保留动画效果)
reverseAnimation.setInterpolator(new
LinearInterpolator());//
匀速变化
//
设置当前headView的状态
state
=
DONE;
//
设置当前下拉刷新是否可用
isRefreshable
=
false;
}
/**
*
测量headView的
宽高
*
*
@param
child
*/
private
void
MeasureView(View
child)
{
ViewGroup.LayoutParams
lp
=
child.getLayoutParams();
if
(null
==
lp)
{
lp
=
new
ViewGroup.LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT);
}
int
measureChildWidth
=
ViewGroup.getChildMeasureSpec(0,
0,
lp.width);
int
measureChildHeight;
if
(lp.height
>
0)
{
measureChildHeight
=
MeasureSpec.makeMeasureSpec(lp.height,
MeasureSpec.EXACTLY);
}
else
{
measureChildHeight
=
MeasureSpec.makeMeasureSpec(0,
MeasureSpec.UNSPECIFIED);
}
child.measure(measureChildWidth,
measureChildHeight);
}
@Override
public
boolean
onTouchEvent(MotionEvent
event)
{
switch
(event.getAction())
{
case
MotionEvent.ACTION_DOWN:
if
(firstVisibleIndex
==
0
&&
!isRecored)
{
startY
=
event.getY();
isRecored
=
true;
}
break;
case
MotionEvent.ACTION_MOVE:
float
tempY
=
event.getY();
if
(firstVisibleIndex
==
0
&&
!isRecored)
{
startY
=
tempY;
isRecored
=
true;
}
if
(state
!=
REFRESHING)
{
if
(state
==
PULL_TO_REFRESH)
{
//
向下拉了
从下拉刷新的状态
来到
松开刷新的状态
if
((tempY
-
startY)
/
RATIO
>=
headContentHeight
&&
(tempY
-
startY)
>
0)
{
state
=
RELEASE_TO_REFRESH;
changeHeadViewOfState();
}
//
向上推了
从下拉刷新的状态
来到
刷新完成的状态
else
if
((tempY
-
startY)
<=
0)
{
state
=
DONE;
changeHeadViewOfState();
}
}
else
if
(state
==
RELEASE_TO_REFRESH)
{
//
向上推了
还没有完全将HEADVIEW
隐藏掉(可以看到一部分)
//
从松开刷新的状态
来到
下拉刷新的状态
if
((tempY
-
startY)
/
RATIO
<
headContentHeight
&&
(tempY
-
startY)
>
0)
{
state
=
PULL_TO_REFRESH;
changeHeadViewOfState();
isBack
=
true;
}
//
向上推了
一下子推到了最上面
从松开刷新的状态
来到
刷新完成的状态
(数据不刷新的)
else
if
((tempY
-
startY)
<=
0)
{
state
=
DONE;
changeHeadViewOfState();
}
}
else
if
(state
==
DONE)
{
//
刷新完成的状态
来到
下拉刷新的状态
if
((tempY
-
startY)
>
0)
{
state
=
PULL_TO_REFRESH;
changeHeadViewOfState();
}
}
if
(state
==
PULL_TO_REFRESH)
{
headView.setPadding(
0,
(int)
((tempY
-
startY)
/
RATIO
-
headContentHeight),
0,
0);
}
if
(state
==
RELEASE_TO_REFRESH)
{
headView.setPadding(
0,
(int)
((tempY
-
startY)
/
RATIO
-
headContentHeight),
0,
0);
}
}
break;
case
MotionEvent.ACTION_UP:
if
(state
!=
REFRESHING)
{
if
(state
==
PULL_TO_REFRESH)
{
//
松手
state
=
DONE;
changeHeadViewOfState();
}
else
if
(state
==
RELEASE_TO_REFRESH)
{
//
松手
state
=
REFRESHING;
changeHeadViewOfState();
//
执行数据刷新方法
onRefresh();
}
}
isRecored
=
false;
isBack
=
false;
break;
}
return
super.onTouchEvent(event);
}
/**
*
执行下拉刷新
*/
private
void
onRefresh()
{
if
(refreshListner
!=
null)
{
refreshListner.onRefresh();
}
}
/**
*
HeadView的状态变化效果
*/
private
void
changeHeadViewOfState()
{
//
switch
(state)
{
case
PULL_TO_REFRESH:
headArrow.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
headTitle.setVisibility(View.VISIBLE);
headLastUpdate.setVisibility(View.VISIBLE);
headArrow.clearAnimation();
headTitle.setText("下拉可以刷新");
//由
松开刷新
到
下拉刷新
if(isBack){
headArrow.startAnimation(animation);
isBack
=
false;
}
break;
case
RELEASE_TO_REFRESH:
headArrow.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
headTitle.setVisibility(View.VISIBLE);
headLastUpdate.setVisibility(View.VISIBLE);
headArrow.clearAnimation();
headArrow.startAnimation(reverseAnimation);
headTitle.setText("松开可以刷新");
break;
case
REFRESHING:
headArrow.setVisibility(View.GONE);
progressBar.setVisibility(View.VISIBLE);
headTitle.setVisibility(View.VISIBLE);
headLastUpdate.setVisibility(View.VISIBLE);
headArrow.clearAnimation();
headTitle.setText("正在刷新...");
headView.setPadding(0,
0,
0,
0);
break;
case
DONE:
headArrow.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
headTitle.setVisibility(View.VISIBLE);
headLastUpdate.setVisibility(View.VISIBLE);
headArrow.clearAnimation();
headTitle.setText("下拉可以刷新");
headView.setPadding(0,
-1
*
headContentHeight,
0,
0);
break;
}
}
private
int
lastPos;//最后一个可见的item的位置
private
int
count;//item总数,注意不是当前可见的item总数
private
boolean
hasFoot
=
false;//是否有了Foot
@Override
public
void
onScroll(AbsListView
view,
int
firstVisibleItem,
int
visibleItemCount,
int
totalItemCount)
{
firstVisibleIndex
=
firstVisibleItem;
lastPos
=
getLastVisiblePosition();
count
=
totalItemCount;
//因为刚进入的时候,lastPos=-1,count=0,这个时候不能让它执行onAddFoot方法
if(lastPos==count-1
&&
!hasFoot
&&
lastPos
!=
-1){
hasFoot
=
true;
onAddFoot();
Log.d("addFoot================","执行添加Foot");
}
Log.d("count================",
count+"");
Log.d("lastPos================",
lastPos+"");
}
@Override
public
void
onScrollStateChanged(AbsListView
view,
int
scrollState)
{
if(isFootLoading)
return;
if(hasFoot
&&
scrollState==SCROLL_STATE_IDLE){
isFootLoading
=
true;
onFootLoading();
}
}
/**
*
设置下拉刷新监听
*
*
@param
listener
*/
public
void
setOnRefreshListner(OnRefreshListner
listener)
{
//
设置下拉刷新可用
isRefreshable
=
true;
refreshListner
=
listener;
}
//执行底部加载
public
void
onFootLoading(){
if(footLoadingListener!=null
&&
isFootLoading)
footLoadingListener.onFootLoading();
}
public
void
setOnAddFootListener(OnAddFootListener
addFootListener){
onAddFootListener
=
addFootListener;
}
//执行添加foot
public
void
onAddFoot(){
if(onAddFootListener!=null
&&
hasFoot)
onAddFootListener.addFoot();
}
//是否添加Foot的监听器,如果写在OnFootLoadingListener中会有延迟,效果不好
//应该是先进入添加Foot的状态,再进入FootLoading的状态
public
OnAddFootListener
onAddFootListener;
//是否进入从底部加载数据的状态的监听器
public
OnFootLoadingListener
footLoadingListener;
//正在加载底部数据
private
boolean
isFootLoading
=
false;
public
void
setOnFootLoadingListener(OnFootLoadingListener
footLoading){
footLoadingListener
=
footLoading;
}
/**
*
下拉刷新监听器
*
@author
lxj
*
*/
public
interface
OnRefreshListner
{
/**
*
下拉刷新的时候,在这里执行获取数据的过程
*/
void
onRefresh();
}
/**
*
上拉刷新监听器
*
@author
lxj
*
*/
public
interface
OnFootLoadingListener{
/**
*
这里是执行后台获取数据的过程
*/
void
onFootLoading();
}
/**
*
添加Foot的监听器
*
@author
lxj
*
*/
public
interface
OnAddFootListener{
/**
*
这里是用户addFootView的操作
*/
void
addFoot();
}
/**
*
底部数据加载完成,用户需要加入一个removeFootView的操作
*/
public
void
onFootLoadingComplete(){
hasFoot
=
false;
isFootLoading
=
false;
}
/**
*
上拉刷新完成时
所执行的操作,更改状态,隐藏head
*/
public
void
onRefreshComplete()
{
state
=
DONE;
changeHeadViewOfState();
headLastUpdate.setText("最后刷新时间:
"
+
new
Date().toLocaleString());
}
@Override
public
void
setAdapter(ListAdapter
adapter)
{
headLastUpdate.setText("最后刷新时间:
"
+
new
Date().toLocaleString());
super.setAdapter(adapter);
}
}下面是布局文件:
main.xml<?xml
version="1.0"
encoding="utf-8"?>
<LinearLayout
xmlns:android="/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<com.test.custom.CustomListView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/listview"
/>
</LinearLayout>head.xml<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true">
<ImageView
android:id="@+id/head_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/arrow"/>
<ProgressBar
android:id="@+id/progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 家庭洗衣知识培训课件
- 儿童清明节活动计划
- 汽车销售培训之思想意识
- 电能表维修知识培训课件
- 技术信息查询服务合同书
- 企业负责人聘用协议
- 利率体制的概念
- 期货风险案例分析
- 三农村居民健康城市创建方案
- 认知心理学与行为分析
- 合作单位综合评价表(综合服务类)
- 可编辑修改中国地图模板
- 人教版六年级上册数学第六单元测试卷(百分数(一))
- 《基础英语》课件 Unit 1 Thinking as a Hobby
- 河南省地图含市县地图矢量分层地图行政区划市县概况ppt模板
- 动画基础知识ppt(完整版)课件
- 中国音乐史PPT讲稿课件
- 桥梁模板施工方案最终版
- 部编版小学六年级书法教案【16课时】电子稿
- 广元九州施工合同正式
- 兰州商学院二级学院权力运行流程图
评论
0/150
提交评论