失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > android listview下拉刷新动画 android 安卓 listview 支持下拉刷新 上拉加载更多

android listview下拉刷新动画 android 安卓 listview 支持下拉刷新 上拉加载更多

时间:2023-01-25 17:41:46

相关推荐

android listview下拉刷新动画 android 安卓 listview 支持下拉刷新 上拉加载更多

【1】重写listViewimportjava.text.SimpleDateFormat;

importjava.util.Date;

importcom.example.testdddleapk.R;

importandroid.content.Context;

importandroid.util.AttributeSet;

importandroid.util.Log;

importandroid.view.MotionEvent;

importandroid.view.View;

importandroid.view.ViewGroup;

importandroid.view.animation.Animation;

importandroid.view.animation.LinearInterpolator;

importandroid.view.animation.RotateAnimation;

importandroid.widget.AbsListView;

importandroid.widget.AbsListView.OnScrollListener;

importandroid.widget.BaseAdapter;

importandroid.widget.ImageView;

importandroid.widget.ListAdapter;

importandroid.widget.ListView;

importandroid.widget.ProgressBar;

importandroid.widget.TextView;

publicclassRefreshListViewextendsListViewimplementsOnScrollListener{

privatestaticfinalintDONE=0;

privatestaticfinalintPULL_TO_REFRESH=1;

privatestaticfinalintRELEASE_TO_REFRESH=2;

privatestaticfinalintREFRESHING=3;

privatestaticfinalfloatRATIO=3;//用来设置实际间距和上边距之间的比例

privateintstate;//当前下拉刷新的状态

privateintfirstVisibleIndex;//在listview中第一个可以看见的item

privateViewheadView;

privateImageViewheadArrow;

privateProgressBarprogressBar;

privateTextViewheadTitle;

privateTextViewheadLastUpdate;

privateintheadContentWidth;

privateintheadContentHeight;

privateAnimationanimation;

privateAnimationreverseAnimation;

privateOnRefreshListnerrefreshListner;//刷新监听器

privatebooleanisRefreshable;

privatebooleanisRecored=false;//用来记录第一次按下坐标点,在整个滑动的过程中只记录一次

privatefloatstartY;

privatebooleanisBack=false;//是从松开刷新状态来到的下拉刷新状态

publicRefreshListView(Contextcontext,AttributeSetattrs){

super(context,attrs);

init(context);

}

privatevoidinit(Contextcontext){

//listview设置滑动时缓冲背景色

setCacheColorHint(0xcc000000);

headView=View.inflate(context,R.layout.listview_header,null);

headArrow=(ImageView)headView.findViewById(R.id.iv_listview_header_arrow);

progressBar=(ProgressBar)headView.findViewById(R.id.pb_listview_header);

headTitle=(TextView)headView.findViewById(R.id.tv_listview_header_last_update_time);

headLastUpdate=(TextView)headView.findViewById(R.id.tv_listview_header_state);

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=newRotateAnimation(-180,0,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);

animation.setDuration(250);

animation.setFillAfter(true);//设定动画结束时,停留在动画结束位置(保留动画效果)

animation.setInterpolator(newLinearInterpolator());//匀速变化

reverseAnimation=newRotateAnimation(0,-180,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);

reverseAnimation.setDuration(200);

reverseAnimation.setFillAfter(true);//设定动画结束时,停留在动画结束位置(保留动画效果)

reverseAnimation.setInterpolator(newLinearInterpolator());//匀速变化

//设置当前headView的状态

state=DONE;

//设置当前下拉刷新是否可用

isRefreshable=false;

}

/**

*测量headView的宽高

*/

privatevoidMeasureView(Viewchild){

ViewGroup.LayoutParamslp=child.getLayoutParams();

if(null==lp){

lp=newViewGroup.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT);

}

intmeasureChildWidth=ViewGroup.getChildMeasureSpec(0,0,lp.width);

intmeasureChildHeight;

if(lp.height>0){

measureChildHeight=MeasureSpec.makeMeasureSpec(lp.height,MeasureSpec.EXACTLY);

}else{

measureChildHeight=MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED);

}

child.measure(measureChildWidth,measureChildHeight);

}

privatefloattempY=0;

privatefloatdownY=0;

@Override

publicbooleanonTouchEvent(MotionEventevent){

switch(event.getAction()){

caseMotionEvent.ACTION_DOWN:

downY=event.getY();

System.out.println("downY:"+downY);

if(firstVisibleIndex==0&&!isRecored){

startY=event.getY();

isRecored=true;

}

break;

caseMotionEvent.ACTION_MOVE:

//floattempY=event.getY();

tempY=event.getY();

System.out.println("tempy:"+tempY);

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();

}

//向上推了从下拉刷新的状态来到刷新完成的状态

elseif((tempY-startY)<=0){

state=DONE;

changeHeadViewOfState();

}

}elseif(state==RELEASE_TO_REFRESH){

//向上推了还没有完全将HEADVIEW隐藏掉(可以看到一部分)

//从松开刷新的状态来到下拉刷新的状态

if((tempY-startY)/RATIO

&&(tempY-startY)>0){

state=PULL_TO_REFRESH;

changeHeadViewOfState();

isBack=true;

}

//向上推了一下子推到了最上面从松开刷新的状态来到刷新完成的状态(数据不刷新的)

elseif((tempY-startY)<=0){

state=DONE;

changeHeadViewOfState();

}

}elseif(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;

caseMotionEvent.ACTION_UP:

if(state!=REFRESHING){

if(state==PULL_TO_REFRESH){

//松手

state=DONE;

changeHeadViewOfState();

}

elseif(state==RELEASE_TO_REFRESH){

//松手

state=REFRESHING;

changeHeadViewOfState();

//执行数据刷新方法

onRefresh();

}

}

isRecored=false;

isBack=false;

break;

}

returnsuper.onTouchEvent(event);

}

/**

*执行下拉刷新

*/

privatevoidonRefresh(){

if(refreshListner!=null){

refreshListner.onRefresh();

}

}

/**

*HeadView的状态变化效果

*/

privatevoidchangeHeadViewOfState(){

switch(state){

casePULL_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;

caseRELEASE_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;

caseREFRESHING:

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;

caseDONE:

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;

}

}

privateintlastPos;//最后一个可见的item的位置

privateintcount;//item总数,注意不是当前可见的item总数

privatebooleanhasFoot=false;//是否有了Foot

publicvoidonScroll(AbsListViewview,intfirstVisibleItem,intvisibleItemCount,inttotalItemCount){

firstVisibleIndex=firstVisibleItem;

lastPos=getLastVisiblePosition();

count=totalItemCount;

//因为刚进入的时候,lastPos=-1,count=0,这个时候不能让它执行onAddFoot方法

if(lastPos==count-1&&!hasFoot&&lastPos!=-1&&((tempY-startY)<0)){

hasFoot=true;

onAddFoot();

}

}

publicvoidonScrollStateChanged(AbsListViewview,intscrollState){

if(isFootLoading)return;

if(lastPos==count-1&&lastPos!=-1&&hasFoot&&footer!=null&&((tempY-downY)>0)){

this.removeFooterView(footer);

}

if(hasFoot&&scrollState==SCROLL_STATE_IDLE&&((tempY-downY)<0)){

isFootLoading=true;

onFootLoading();

}

}

/**

*设置下拉刷新监听

*/

publicvoidsetOnRefreshListner(OnRefreshListnerlistener){

//设置下拉刷新可用

isRefreshable=true;

refreshListner=listener;

}

//执行底部加载

publicvoidonFootLoading(){

if(footLoadingListener!=null&&isFootLoading&&hasFoot&&(tempY-downY)<0){

footLoadingListener.onFootLoading();}

}

publicvoidsetOnAddFootListener(OnAddFootListeneraddFootListener){

onAddFootListener=addFootListener;

}

//执行添加foot

publicvoidonAddFoot(){

if(onAddFootListener!=null&&hasFoot)

onAddFootListener.addFoot();

}

//是否添加Foot的监听器,如果写在OnFootLoadingListener中会有延迟,效果不好

//应该是先进入添加Foot的状态,再进入FootLoading的状态

publicOnAddFootListeneronAddFootListener;

//是否进入从底部加载数据的状态的监听器

publicOnFootLoadingListenerfootLoadingListener;

//正在加载底部数据

privatebooleanisFootLoading=false;

publicvoidsetOnFootLoadingListener(OnFootLoadingListenerfootLoading){

footLoadingListener=footLoading;

}

/**

*下拉刷新监听器

*/

publicinterfaceOnRefreshListner{

//下拉刷新的时候,在这里执行获取数据的过程

voidonRefresh();

}

privateViewfooter=null;

publicvoidsetFooter(Viewfooter){

this.footer=footer;

}

/**

*上拉刷新监听器

*/

publicinterfaceOnFootLoadingListener{

//这里是执行后台获取数据的过程

voidonFootLoading();

}

/**

*添加Foot的监听器

*/

publicinterfaceOnAddFootListener{

//这里是用户addFootView的操作

voidaddFoot();

}

/**

*底部数据加载完成,用户需要加入一个removeFootView的操作

*/

publicvoidonFootLoadingComplete(){

hasFoot=false;

isFootLoading=false;

}

/**

*上拉刷新完成时所执行的操作,更改状态,隐藏head

*/

publicvoidonRefreshComplete(){

state=DONE;

changeHeadViewOfState();

headLastUpdate.setText("最后刷新时间:"+newDate().toLocaleString());

}

@Override

publicvoidsetAdapter(ListAdapteradapter){

headLastUpdate.setText("最后刷新时间:"+newDate().toLocaleString());

super.setAdapter(adapter);

}

}

【2】下拉刷新头部布局文件listview_header.xml<?xml version="1.0"encoding="utf-8"?>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="horizontal">

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_margin="10dip">

android:id="@+id/iv_listview_header_arrow"

android:layout_width="40dp"

android:layout_height="40dp"

android:layout_gravity="center"

android:minWidth="30dip"

android:src="@drawable/arrow"/>

android:id="@+id/pb_listview_header"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center"

android:indeterminateDrawable="@drawable/common_progressbar"

android:visibility="gone"/>

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:layout_gravity="center_vertical"

android:gravity="center_horizontal"

android:orientation="vertical">

android:id="@+id/tv_listview_header_state"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="下拉刷新"

android:textColor="#FF0000"

android:textSize="18sp"/>

android:id="@+id/tv_listview_header_last_update_time"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginTop="5dip"

android:text="最后刷新时间:-10-1012:56:12"

android:textColor="@android:color/white"

android:textSize="14sp"/>

【3】上拉加载更多布局文件listview_footer.xml<?xml version="1.0"encoding="utf-8"?>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="vertical">

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center_horizontal"

android:layout_margin="10dip"

android:gravity="center_vertical"

android:orientation="horizontal">

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center"

android:indeterminateDrawable="@drawable/common_progressbar"/>

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginLeft="10dip"

android:text="加载更多..."

android:textColor="#FF0000"

android:textSize="18sp"/>

【4】progressBar--common_progressbar.xml<?xml version="1.0"encoding="utf-8"?>

android:fromDegrees="0"

android:pivotX="50%"

android:pivotY="50%"

android:toDegrees="360">

android:innerRadiusRatio="3"

android:shape="ring"

android:useLevel="false">

android:centerColor="#FF6666"

android:endColor="#FF0000"

android:startColor="#FFFFFF"

android:type="sweep"/>

【5】使用方法adapter=newmyListAdapter(items,xxx.this);

listView.setAdapter(adapter);

/**

*下拉刷新回调

*/

listView.setOnRefreshListner(newOnRefreshListner(){

publicvoidonRefresh(){

newAsyncTask>(){

@Override

protectedArrayListdoInBackground(Void...params){

try{

//模拟从服务器获取数据的过程

Thread.sleep(1500);

}catch(InterruptedExceptione){

e.printStackTrace();

}

returnnull;

}

//更新UI的方法,系统自动实现

@Override

protectedvoidonPostExecute(ArrayListresult){

data.addAll(0,result);//注意是往前添加数据

adapter.notifyDataSetChanged();

listView.onRefreshComplete();//完成下拉刷新,这个方法要调用

super.onPostExecute(result);

}

}.execute();

}

});

//上拉加载更多功能

finalViewfooter=View.inflate(getActivity(),R.layout.listview_footer,null);

listView.setOnAddFootListener(newOnAddFootListener(){

publicvoidaddFoot(){

listView.setFooter(footer);

listView.addFooterView(footer);

}

});

listView.setOnFootLoadingListener(newOnFootLoadingListener(){

publicvoidonFootLoading(){

newAsyncTask>(){

@Override

protectedArrayListdoInBackground(Void...params){

try{

//模拟从服务器获取数据的过程

Thread.sleep(2000);

}catch(InterruptedExceptione){

e.printStackTrace();

}

returnnull;

}

//在doInBackground后面执行

protectedvoidonPostExecute(ArrayListresult){

data.addAll(result);//这个是往后添加数据

adapter.notifyDataSetChanged();

listView.onFootLoadingComplete();//完成上拉刷新,就是底部加载完毕,这个方法要调用

//移除footer,这个动作不能少

listView.removeFooterView(footer);

super.onPostExecute(result);

}

}.execute();

}

});

【6】注意事项

listview设置项目点击事件

listView.setOnItemClickListener(new OnItemClickListener() {

public void onItemClick(AdapterView> parent, View view,int position, long id) {

if(position==0||position==items.length()+1) return;

//获取每项的数据,position需减1,第0项为listview_head

}

如果觉得《android listview下拉刷新动画 android 安卓 listview 支持下拉刷新 上拉加载更多》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。