版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】android安卓自定义listview实现下拉刷新
【1】、重写listViewpublic
class
MyListView
extends
ListView
implements
OnScrollListener
{
private
final
static
int
RELEASE_To_REFRESH
=
0;//
下拉过程的状态值
private
final
static
int
PULL_To_REFRESH
=
1;
//
从下拉返回到不刷新的状态值
private
final
static
int
REFRESHING
=
2;//
正在刷新的状态值
private
final
static
int
DONE
=
3;
private
final
static
int
LOADING
=
4;
//
实际的padding的距离与界面上偏移距离的比例
private
final
static
int
RATIO
=
3;
private
LayoutInflater
inflater;
//
ListView头部下拉刷新的布局
private
LinearLayout
headerView;
private
TextView
lvHeaderTipsTv;
private
TextView
lvHeaderLastUpdatedTv;
private
ImageView
lvHeaderArrowIv;
private
ProgressBar
lvHeaderProgressBar;
//
定义头部下拉刷新的布局的高度
private
int
headerContentHeight;
private
RotateAnimation
animation;
private
RotateAnimation
reverseAnimation;
private
int
startY;
private
int
state;
private
boolean
isBack;
//
用于保证startY的值在一个完整的touch事件中只被记录一次
private
boolean
isRecored;
private
OnRefreshListener
refreshListener;
private
boolean
isRefreshable;
public
MyListView(Context
context)
{
super(context);
init(context);
}
public
MyListView(Context
context,
AttributeSet
attrs)
{
super(context,
attrs);
init(context);
}
private
void
init(Context
context)
{
setCacheColorHint(context.getResources().getColor(R.color.transparent));
inflater
=
LayoutInflater.from(context);
headerView
=
(LinearLayout)
inflater.inflate(R.layout.lv_header,
null);
lvHeaderTipsTv
=
(TextView)
headerView
.findViewById(R.id.lvHeaderTipsTv);
lvHeaderLastUpdatedTv
=
(TextView)
headerView
.findViewById(R.id.lvHeaderLastUpdatedTv);
lvHeaderArrowIv
=
(ImageView)
headerView
.findViewById(R.id.lvHeaderArrowIv);
//
设置下拉刷新图标的最小高度和宽度
lvHeaderArrowIv.setMinimumWidth(70);
lvHeaderArrowIv.setMinimumHeight(50);
lvHeaderProgressBar
=
(ProgressBar)
headerView
.findViewById(R.id.lvHeaderProgressBar);
measureView(headerView);
headerContentHeight
=
headerView.getMeasuredHeight();
//
设置内边距,正好距离顶部为一个负的整个布局的高度,正好把头部隐藏
headerView.setPadding(0,
-1
*
headerContentHeight,
0,
0);
//
重绘一下
headerView.invalidate();
//
将下拉刷新的布局加入ListView的顶部
addHeaderView(headerView,
null,
false);
//
设置滚动监听事件
setOnScrollListener(this);
//
设置旋转动画事件
animation
=
new
RotateAnimation(0,
-180,
RotateAnimation.RELATIVE_TO_SELF,
0.5f,
RotateAnimation.RELATIVE_TO_SELF,
0.5f);
animation.setInterpolator(new
LinearInterpolator());
animation.setDuration(250);
animation.setFillAfter(true);
reverseAnimation
=
new
RotateAnimation(-180,
0,
RotateAnimation.RELATIVE_TO_SELF,
0.5f,
RotateAnimation.RELATIVE_TO_SELF,
0.5f);
reverseAnimation.setInterpolator(new
LinearInterpolator());
reverseAnimation.setDuration(200);
reverseAnimation.setFillAfter(true);
//
一开始的状态就是下拉刷新完的状态,所以为DONE
state
=
DONE;
//
是否正在刷新
isRefreshable
=
false;
}
@Override
public
void
onScrollStateChanged(AbsListView
view,
int
scrollState)
{
}
@Override
public
void
onScroll(AbsListView
view,
int
firstVisibleItem,
int
visibleItemCount,
int
totalItemCount)
{
if
(firstVisibleItem
==
0)
{
isRefreshable
=
true;
}
else
{
isRefreshable
=
false;
}
}
@Override
public
boolean
onTouchEvent(MotionEvent
ev)
{
if
(isRefreshable)
{
switch
(ev.getAction())
{
case
MotionEvent.ACTION_DOWN:
if
(!isRecored)
{
isRecored
=
true;
startY
=
(int)
ev.getY();//
手指按下时记录当前位置
}
break;
case
MotionEvent.ACTION_UP:
if
(state
!=
REFRESHING
&&
state
!=
LOADING)
{
if
(state
==
PULL_To_REFRESH)
{
state
=
DONE;
changeHeaderViewByState();
}
if
(state
==
RELEASE_To_REFRESH)
{
state
=
REFRESHING;
changeHeaderViewByState();
onLvRefresh();
}
}
isRecored
=
false;
isBack
=
false;
break;
case
MotionEvent.ACTION_MOVE:
int
tempY
=
(int)
ev.getY();
if
(!isRecored)
{
isRecored
=
true;
startY
=
tempY;
}
if
(state
!=
REFRESHING
&&
isRecored
&&
state
!=
LOADING)
{
//
保证在设置padding的过程中,当前的位置一直是在head,否则如果当列表超出屏幕的话,当在上推的时候,列表会同时进行滚动
//
可以松手去刷新了
if
(state
==
RELEASE_To_REFRESH)
{
setSelection(0);
//
往上推了,推到了屏幕足够掩盖head的程度,但是还没有推到全部掩盖的地步
if
(((tempY
-
startY)
/
RATIO
<
headerContentHeight)//
由松开刷新状态转变到下拉刷新状态
&&
(tempY
-
startY)
>
0)
{
state
=
PULL_To_REFRESH;
changeHeaderViewByState();
}
//
一下子推到顶了
else
if
(tempY
-
startY
<=
0)
{//
由松开刷新状态转变到done状态
state
=
DONE;
changeHeaderViewByState();
}
}
//
还没有到达显示松开刷新的时候,DONE或者是PULL_To_REFRESH状态
if
(state
==
PULL_To_REFRESH)
{
setSelection(0);
//
下拉到可以进入RELEASE_TO_REFRESH的状态
if
((tempY
-
startY)
/
RATIO
>=
headerContentHeight)
{//
由done或者下拉刷新状态转变到松开刷新
state
=
RELEASE_To_REFRESH;
isBack
=
true;
changeHeaderViewByState();
}
//
上推到顶了
else
if
(tempY
-
startY
<=
0)
{//
由DOne或者下拉刷新状态转变到done状态
state
=
DONE;
changeHeaderViewByState();
}
}
//
done状态下
if
(state
==
DONE)
{
if
(tempY
-
startY
>
0)
{
state
=
PULL_To_REFRESH;
changeHeaderViewByState();
}
}
//
更新headView的size
if
(state
==
PULL_To_REFRESH)
{
headerView.setPadding(0,
-1
*
headerContentHeight
+
(tempY
-
startY)
/
RATIO,
0,
0);
}
//
更新headView的paddingTop
if
(state
==
RELEASE_To_REFRESH)
{
headerView.setPadding(0,
(tempY
-
startY)
/
RATIO
-
headerContentHeight,
0,
0);
}
}
break;
default:
break;
}
}
return
super.onTouchEvent(ev);
}
//
当状态改变时候,调用该方法,以更新界面
private
void
changeHeaderViewByState()
{
switch
(state)
{
case
RELEASE_To_REFRESH:
lvHeaderArrowIv.setVisibility(View.VISIBLE);
lvHeaderProgressBar.setVisibility(View.GONE);
lvHeaderTipsTv.setVisibility(View.VISIBLE);
lvHeaderLastUpdatedTv.setVisibility(View.VISIBLE);
lvHeaderArrowIv.clearAnimation();//
清除动画
lvHeaderArrowIv.startAnimation(animation);//
开始动画效果
lvHeaderTipsTv.setText("松开刷新");
break;
case
PULL_To_REFRESH:
lvHeaderProgressBar.setVisibility(View.GONE);
lvHeaderTipsTv.setVisibility(View.VISIBLE);
lvHeaderLastUpdatedTv.setVisibility(View.VISIBLE);
lvHeaderArrowIv.clearAnimation();
lvHeaderArrowIv.setVisibility(View.VISIBLE);
//
是由RELEASE_To_REFRESH状态转变来的
if
(isBack)
{
isBack
=
false;
lvHeaderArrowIv.clearAnimation();
lvHeaderArrowIv.startAnimation(reverseAnimation);
lvHeaderTipsTv.setText("下拉刷新");
}
else
{
lvHeaderTipsTv.setText("下拉刷新");
}
break;
case
REFRESHING:
headerView.setPadding(0,
0,
0,
0);
lvHeaderProgressBar.setVisibility(View.VISIBLE);
lvHeaderArrowIv.clearAnimation();
lvHeaderArrowIv.setVisibility(View.GONE);
lvHeaderTipsTv.setText("正在刷新...");
lvHeaderLastUpdatedTv.setVisibility(View.VISIBLE);
break;
case
DONE:
headerView.setPadding(0,
-1
*
headerContentHeight,
0,
0);
lvHeaderProgressBar.setVisibility(View.GONE);
lvHeaderArrowIv.clearAnimation();
lvHeaderArrowIv.setImageResource(R.drawable.arrow);
lvHeaderTipsTv.setText("下拉刷新");
lvHeaderLastUpdatedTv.setVisibility(View.VISIBLE);
break;
}
}
//
此方法直接照搬自网络上的一个下拉刷新的demo,此处是“估计”headView的width以及height
private
void
measureView(View
child)
{
ViewGroup.LayoutParams
params
=
child.getLayoutParams();
if
(params
==
null)
{
params
=
new
ViewGroup.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
int
childWidthSpec
=
ViewGroup.getChildMeasureSpec(0,
0
+
0,
params.width);
int
lpHeight
=
params.height;
int
childHeightSpec;
if
(lpHeight
>
0)
{
childHeightSpec
=
MeasureSpec.makeMeasureSpec(lpHeight,
MeasureSpec.EXACTLY);
}
else
{
childHeightSpec
=
MeasureSpec.makeMeasureSpec(0,
MeasureSpec.UNSPECIFIED);
}
child.measure(childWidthSpec,
childHeightSpec);
}
public
void
setonRefreshListener(OnRefreshListener
refreshListener)
{
this.refreshListener
=
refreshListener;
isRefreshable
=
true;
}
public
interface
OnRefreshListener
{
public
void
onRefresh();
}
public
void
onRefreshComplete()
{
state
=
DONE;
lvHeaderLastUpdatedTv.setText("最近更新:"
+
new
Date().toLocaleString());
changeHeaderViewByState();
}
private
void
onLvRefresh()
{
if
(refreshListener
!=
null)
{
refreshListener.onRefresh();
}
}
public
void
setAdapter(BaseAdapter
adapter)
{
lvHeaderLastUpdatedTv.setText("最近更新:"
+
new
Date().toLocaleString());
super.setAdapter(adapter);
}
}【2】刷新头部xml文件lv_header.xml<?xml
version="1.0"
encoding="utf-8"?>
<!--
ListView的头部
-->
<LinearLayout
xmlns:android="/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#000000"
>
<!--
内容
-->
<RelativeLayout
android:id="@+id/head_contentLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="30dp"
>
<!--
箭头图像、进度条
-->
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
>
<!--
箭头
-->
<ImageView
android:id="@+id/lvHeaderArrowIv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/arrow"
/>
<!--
进度条
-->
<ProgressBar
android:id="@+id/lvHeaderProgressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone"
/>
</FrameLayout>
<!--
提示、最近更新
-->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:gravity="center_horizontal"
android:orientation="vertical"
>
<!--
提示
-->
<TextView
android:id="@+id/lvHeaderTipsTv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
andr
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 金融科技在消费金融中的安全保障措施研究
- 大健康产业运营及营销推广策略研究
- 公司产品专员招聘要点分析
- 企业技术转化中的创新思路与方法探讨
- 旅游行业导游员岗位面试技巧指导
- 教育装备公司业务销售经理招聘策略全解析
- 劳动保障医保就业前景
- 制造业总经理面试常见问题
- 法规事务部业务培训计划及执行情况反馈
- 物流公司经理面试全解析
- GB/T 14692-2008技术制图投影法
- 六年级上册数学试题 - 分数乘除章节测试 苏教版(图片版)无答案
- 瑞幸CMO杨飞:互联网营销的流量池思维PP课件
- 物业服务企业消防培训课件(法律法规)
- 公共营养师考试试题(含答案)
- 罗氏治疗药物监测(TDM)概述及竞争分析课件
- 特种设备作业人员补(换)证申请表
- 《材料分析测试技术》全套教学课件
- 四川大学办公用房管理实施细则
- 高中数学必修二 6.2.1 平面向量的加法运算
- 大众文化导论完整版课件最全电子教案
评论
0/150
提交评论