android利用ListView滑动刷新
16lz
2021-12-04
packagecom.laohuai.appdemo.customui;importjava.util.ArrayList;importjava.util.List;importcom.laohuai.appdemo.customui.ui.MyListView;importcom.laohuai.appdemo.customui.ui.MyListView.OnRefreshListener;importandroid.app.Activity;importandroid.os.AsyncTask;importandroid.os.Bundle;importandroid.view.View;importandroid.view.ViewGroup;importandroid.widget.BaseAdapter;importandroid.widget.TextView;publicclassMainActivityextendsActivity{privateList<String>data;privateBaseAdapteradapter;publicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);data=newArrayList<String>();data.add("a");data.add("b");data.add("c");data.add("a");data.add("b");finalMyListViewlistView=(MyListView)findViewById(R.id.listView);adapter=newBaseAdapter(){publicViewgetView(intposition,ViewconvertView,ViewGroupparent){TextViewtv=newTextView(getApplicationContext());tv.setText(data.get(position));returntv;}publiclonggetItemId(intposition){return0;}publicObjectgetItem(intposition){returnnull;}publicintgetCount(){returndata.size();}};listView.setAdapter(adapter);listView.setonRefreshListener(newOnRefreshListener(){publicvoidonRefresh(){newAsyncTask<Void,Void,Void>(){protectedVoiddoInBackground(Void...params){try{Thread.sleep(3000);//刷新3秒}catch(Exceptione){e.printStackTrace();}data.add("刷新后添加的内容");returnnull;}@OverrideprotectedvoidonPostExecute(Voidresult){adapter.notifyDataSetChanged();listView.onRefreshComplete();}}.execute(null,null,null);}});}}packagecom.laohuai.appdemo.customui.ui;importjava.util.Date;importcom.laohuai.appdemo.customui.R;importandroid.content.Context;importandroid.util.AttributeSet;importandroid.util.Log;importandroid.view.LayoutInflater;importandroid.view.MotionEvent;importandroid.view.View;importandroid.view.ViewGroup;importandroid.view.animation.LinearInterpolator;importandroid.view.animation.RotateAnimation;importandroid.widget.AbsListView;importandroid.widget.BaseAdapter;importandroid.widget.ImageView;importandroid.widget.LinearLayout;importandroid.widget.ListView;importandroid.widget.AbsListView.OnScrollListener;importandroid.widget.ProgressBar;importandroid.widget.TextView;publicclassMyListViewextendsListViewimplementsOnScrollListener{privatestaticfinalStringTAG="listview";privatefinalstaticintRELEASE_To_REFRESH=0;privatefinalstaticintPULL_To_REFRESH=1;privatefinalstaticintREFRESHING=2;privatefinalstaticintDONE=3;privatefinalstaticintLOADING=4;//实际的padding的距离与界面上偏移距离的比例privatefinalstaticintRATIO=3;privateLayoutInflaterinflater;//一个线性布局类对象,设置一个可选布局区域privateLinearLayoutheadView;privateTextViewtipsTextview;privateTextViewlastUpdatedTextView;privateImageViewarrowImageView;privateProgressBarprogressBar;privateRotateAnimationanimation;privateRotateAnimationreverseAnimation;//用于保证startY的值在一个完整的touch事件中只被记录一次privatebooleanisRecored;privateintheadContentWidth;privateintheadContentHeight;privateintstartY;privateintfirstItemIndex;privateintstate;privatebooleanisBack;privateOnRefreshListenerrefreshListener;privatebooleanisRefreshable;//新建时自动调用构造函数publicMyListView(Contextcontext){super(context);init(context);}//新建时自动调用构造函数publicMyListView(Contextcontext,AttributeSetattrs){super(context,attrs);init(context);}privatevoidinit(Contextcontext){//拖动时背景黑色设置setCacheColorHint(context.getResources().getColor(R.color.transparent));//---------设置项目前面的显示---------inflater=LayoutInflater.from(context);headView=(LinearLayout)inflater.inflate(R.layout.head,null);//获取箭头对象arrowImageView=(ImageView)headView.findViewById(R.id.head_arrowImageView);arrowImageView.setMinimumWidth(70);arrowImageView.setMinimumHeight(50);//进度条progressBar=(ProgressBar)headView.findViewById(R.id.head_progressBar);//下拉刷新、上拉刷新tipsTextview=(TextView)headView.findViewById(R.id.head_tipsTextView);//最近更新lastUpdatedTextView=(TextView)headView.findViewById(R.id.head_lastUpdatedTextView);measureView(headView);headContentHeight=headView.getMeasuredHeight();headContentWidth=headView.getMeasuredWidth();//和父类比较,(上下左右)的view之间的距离headView.setPadding(0,-1*headContentHeight,0,0);headView.invalidate();Log.v("size","width:"+headContentWidth+"height:"+headContentHeight);//下面两句极其重要,一方面将listView和headView绑定,一方面监听操作addHeaderView(headView,null,false);setOnScrollListener(this);//下面没看懂,待查animation=newRotateAnimation(0,-180,RotateAnimation.RELATIVE_TO_SELF,0.5f,RotateAnimation.RELATIVE_TO_SELF,0.5f);animation.setInterpolator(newLinearInterpolator());animation.setDuration(250);animation.setFillAfter(true);reverseAnimation=newRotateAnimation(-180,0,RotateAnimation.RELATIVE_TO_SELF,0.5f,RotateAnimation.RELATIVE_TO_SELF,0.5f);reverseAnimation.setInterpolator(newLinearInterpolator());reverseAnimation.setDuration(200);reverseAnimation.setFillAfter(true);state=DONE;isRefreshable=false;}publicvoidonScroll(AbsListViewarg0,intfirstVisiableItem,intarg2,intarg3){//滚动时一直回调,直到停止滚动时才停止回调。单击时不回调。刷新//onTouchEvent调用后总会回调一次//firstVisibleItem:当前能看见的第一个列表项ID(从0开始),总是0//arg2:当前能看见的列表项个数(小半个也算)listView个数//arg3:列表项共数,listView个数//Log.d(TAG,"firstItemIndex:"+firstItemIndex);firstItemIndex=firstVisiableItem;}//点击或滑动都会触发publicvoidonScrollStateChanged(AbsListViewarg0,intarg1){}publicbooleanonTouchEvent(MotionEventevent){if(isRefreshable){switch(event.getAction()){caseMotionEvent.ACTION_DOWN:if(firstItemIndex==0&&!isRecored){isRecored=true;startY=(int)event.getY();Log.v(TAG,"在down时候记录当前位置‘");}break;caseMotionEvent.ACTION_UP:if(state!=REFRESHING&&state!=LOADING){if(state==DONE){//什么都不做}if(state==PULL_To_REFRESH){state=DONE;changeHeaderViewByState();//有下拉但没刷新Log.v(TAG,"由下拉刷新状态,到done状态");}if(state==RELEASE_To_REFRESH){state=REFRESHING;//因为异步执行,所以下面两句一起进行,由onRefresh决定什么时候改变状态,//因为会调用onRefreshComplete()changeHeaderViewByState();onRefresh();//有下拉并且刷新Log.v(TAG,"由松开刷新状态,到done状态");}}isRecored=false;isBack=false;break;//当触摸时移动操作时调用caseMotionEvent.ACTION_MOVE:inttempY=(int)event.getY();if(!isRecored&&firstItemIndex==0){Log.v(TAG,"在move时候记录下位置");isRecored=true;startY=tempY;}if(state!=REFRESHING&&isRecored&&state!=LOADING){//保证在设置padding的过程中,当前的位置一直是在head,否则如果当列表超出屏幕的话,当在上推的时候,列表会同时进行滚动//可以松手去刷新了if(state==RELEASE_To_REFRESH){setSelection(0);//往上推了,推到了屏幕足够掩盖head的程度,但是还没有推到全部掩盖的地步if(((tempY-startY)/RATIO<headContentHeight)&&(tempY-startY)>0){state=PULL_To_REFRESH;changeHeaderViewByState();Log.v(TAG,"由松开刷新状态转变到下拉刷新状态");}//一下子推到顶了elseif(tempY-startY<=0){state=DONE;changeHeaderViewByState();Log.v(TAG,"由松开刷新状态转变到done状态");}//往下拉了,或者还没有上推到屏幕顶部掩盖head的地步else{//不用进行特别的操作,只用更新paddingTop的值就行了}}//还没有到达显示松开刷新的时候,DONE或者是PULL_To_REFRESH状态if(state==PULL_To_REFRESH){setSelection(0);//下拉到可以进入RELEASE_TO_REFRESH的状态if((tempY-startY)/RATIO>=headContentHeight){state=RELEASE_To_REFRESH;isBack=true;changeHeaderViewByState();Log.v(TAG,"由done或者下拉刷新状态转变到松开刷新");}//上推到顶了elseif(tempY-startY<=0){state=DONE;changeHeaderViewByState();Log.v(TAG,"由DOne或者下拉刷新状态转变到done状态");}}//done状态下if(state==DONE){if(tempY-startY>0){state=PULL_To_REFRESH;changeHeaderViewByState();}}//更新headView的sizeif(state==PULL_To_REFRESH){headView.setPadding(0,-1*headContentHeight+(tempY-startY)/RATIO,0,0);}//更新headView的paddingTopif(state==RELEASE_To_REFRESH){headView.setPadding(0,(tempY-startY)/RATIO-headContentHeight,0,0);}}break;}}returnsuper.onTouchEvent(event);}//当状态改变时候,调用该方法,以更新界面privatevoidchangeHeaderViewByState(){switch(state){caseRELEASE_To_REFRESH:arrowImageView.setVisibility(View.VISIBLE);progressBar.setVisibility(View.GONE);tipsTextview.setVisibility(View.VISIBLE);lastUpdatedTextView.setVisibility(View.VISIBLE);arrowImageView.clearAnimation();//方向arrowImageView.startAnimation(animation);tipsTextview.setText("松开刷新");Log.v(TAG,"当前状态,松开刷新");break;casePULL_To_REFRESH:progressBar.setVisibility(View.GONE);tipsTextview.setVisibility(View.VISIBLE);lastUpdatedTextView.setVisibility(View.VISIBLE);arrowImageView.clearAnimation();arrowImageView.setVisibility(View.VISIBLE);//是由RELEASE_To_REFRESH状态转变来的if(isBack){isBack=false;arrowImageView.clearAnimation();//方向arrowImageView.startAnimation(reverseAnimation);tipsTextview.setText("下拉刷新");}else{tipsTextview.setText("下拉刷新");}Log.v(TAG,"当前状态,下拉刷新");break;caseREFRESHING:headView.setPadding(0,0,0,0);progressBar.setVisibility(View.VISIBLE);arrowImageView.clearAnimation();arrowImageView.setVisibility(View.GONE);tipsTextview.setText("正在刷新...");lastUpdatedTextView.setVisibility(View.VISIBLE);Log.v(TAG,"当前状态,正在刷新...");break;caseDONE:headView.setPadding(0,-1*headContentHeight,0,0);progressBar.setVisibility(View.GONE);arrowImageView.clearAnimation();arrowImageView.setImageResource(R.drawable.arrow);tipsTextview.setText("下拉刷新");lastUpdatedTextView.setVisibility(View.VISIBLE);Log.v(TAG,"当前状态,done");break;}}publicvoidsetonRefreshListener(OnRefreshListenerrefreshListener){this.refreshListener=refreshListener;isRefreshable=true;}publicinterfaceOnRefreshListener{publicvoidonRefresh();}publicvoidonRefreshComplete(){state=DONE;lastUpdatedTextView.setText("最近更新:"+newDate().toLocaleString());changeHeaderViewByState();}privatevoidonRefresh(){if(refreshListener!=null){refreshListener.onRefresh();}}//此方法直接照搬自网络上的一个下拉刷新的demo,此处是“估计”headView的width以及height//1.staticintgetMode(intmeasureSpec):根据提供的测量值(格式)提取模式(上述三个模式之一)//2.staticintgetSize(intmeasureSpec):根据提供的测量值(格式)提取大小值(这个大小也就是我们通常所说的大小)//3.staticintmakeMeasureSpec(intsize,intmode):根据提供的大小值和模式创建一个测量值(格式)privatevoidmeasureView(Viewchild){ViewGroup.LayoutParamsp=child.getLayoutParams();if(p==null){p=newViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);}intchildWidthSpec=ViewGroup.getChildMeasureSpec(0,0+0,p.width);intlpHeight=p.height;//高度格式// 一个MeasureSpec封装了父布局传递给子布局的布局要求intchildHeightSpec;if(lpHeight>0){//EXACTLY(完全),父元素决定子元素的确切大小,子元素将被限定在给定的边界里而忽略它本身大小childHeightSpec=MeasureSpec.makeMeasureSpec(lpHeight,MeasureSpec.EXACTLY);Log.d(TAG,"lpHeight:"+lpHeight);}else{//UNSPECIFIED(未指定),在高度上父元素不对子元素施加任何束缚childHeightSpec=MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED);//测试的时候发现是-2Log.d(TAG,"lpHeight:"+lpHeight);}//宽度保持不变//测试的时候childWidthSpec,childHeightSpec都是0child.measure(childWidthSpec,childHeightSpec);}publicvoidsetAdapter(BaseAdapteradapter){lastUpdatedTextView.setText("最近更新:"+newDate().toLocaleString());super.setAdapter(adapter);}}<?xmlversion="1.0"encoding="utf-8"?><!--ListView的头部--><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="wrap_content"><!--内容--><RelativeLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:id="@+id/head_contentLayout"android:paddingLeft="30dp"><!--箭头图像、进度条--><FrameLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentLeft="true"android:layout_centerVertical="true"><!--箭头--><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:src="@drawable/arrow"android:id="@+id/head_arrowImageView"/><!--进度条--><ProgressBarandroid:layout_width="wrap_content"android:layout_height="wrap_content"style="?android:attr/progressBarStyleSmall"android:layout_gravity="center"android:id="@+id/head_progressBar"android:visibility="gone"/></FrameLayout><!--提示、最近更新--><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerHorizontal="true"android:orientation="vertical"android:gravity="center_horizontal"><!--提示--><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="下拉刷新"android:textColor="@color/white"android:textSize="20sp"android:id="@+id/head_tipsTextView"/><!--最近更新--><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/head_lastUpdatedTextView"android:text="最近更新"android:textColor="@color/gold"android:textSize="10sp"/></LinearLayout></RelativeLayout></LinearLayout><?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="fill_parent"android:background="#000066"android:orientation="vertical"><com.laohuai.appdemo.customui.ui.MyListViewandroid:layout_width="fill_parent"android:layout_height="fill_parent"android:id="@+id/listView"/></LinearLayout>
更多相关文章
- Android简单实现透明状态栏、去除标题
- Android官方下拉选择控件Spinner
- android判断用户网络类型
- Android(安卓)studio XListView 插件应用
- 使用Android系统自带的下拉刷新控件
- android 隐藏状态栏和标题栏
- Android如何判断网络状态是否良好
- Android(安卓)Banner 简单实现
- Android中隐藏状态栏和标题栏的方法