GridView基于pulltorefresh实现下拉刷新 上拉加载更多功能(推荐)
原理和listview一样,都是重写Android原生控件
Activity
packagecom.example.refreshgridview; importjava.util.ArrayList; importjava.util.List; importandroid.app.Activity; importandroid.os.Bundle; importandroid.widget.GridView; importandroid.widget.Toast; importcom.example.refreshgridview.PullToRefreshBase.OnRefreshListener; publicclassMainActivityextendsActivity{ privatePullToRefreshGridViewmPullRefreshGridView; privateGridViewmGridView; privateGridViewAdapteradapter; @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mPullRefreshGridView=(PullToRefreshGridView)findViewById(R.id.video_gridView); mPullRefreshGridView.init(PullToRefreshGridView.MODE_BOTH); mGridView=mPullRefreshGridView.getRefreshableView(); mPullRefreshGridView.setOnRefreshListener(refreshListener); List<String>list=newArrayList<String>(); for(inti=0;i<40;i++){ list.add(i+""); } adapter=newGridViewAdapter(MainActivity.this,list); mGridView.setAdapter(adapter); } privateOnRefreshListenerrefreshListener=newOnRefreshListener(){ @Override publicvoidonRefresh(intmode){ if(PullToRefreshGridView.MODE_PULL_DOWN_TO_REFRESH==mPullRefreshGridView.getCurrentMode()){ Toast.makeText(MainActivity.this,"下拉刷新",Toast.LENGTH_SHORT).show(); mPullRefreshGridView.onRefreshComplete(); }elseif(mode==PullToRefreshGridView.MODE_PULL_UP_TO_REFRESH){ //加载更多 Toast.makeText(MainActivity.this,"上拉加载更多",Toast.LENGTH_SHORT).show(); mPullRefreshGridView.onRefreshComplete(); } } }; }
adapter
packagecom.example.refreshgridview; importjava.util.ArrayList; importjava.util.List; importandroid.content.Context; importandroid.content.Intent; importandroid.text.TextUtils; importandroid.view.LayoutInflater; importandroid.view.View; importandroid.view.ViewGroup; importandroid.widget.BaseAdapter; importandroid.widget.TextView; publicclassGridViewAdapterextendsBaseAdapter{ privateList<String>mList=newArrayList<String>(); privateContextmContext; publicGridViewAdapter(Contextcontext,List<String>list){ super(); this.mContext=context; this.mList=list; } @Override publicintgetCount(){ returnmList.size(); } @Override publicStringgetItem(intposition){ returnmList.get(position); } @Override publiclonggetItemId(intposition){ returnposition; } @Override publicViewgetView(intposition,ViewconvertView,ViewGroupparent){ ChildHolderOneholder; if(convertView==null){ convertView=LayoutInflater.from(mContext).inflate(R.layout.item_grid_live_show,parent,false); holder=newChildHolderOne(); holder.tvTitle=(TextView)convertView.findViewById(R.id.title_tv); convertView.setTag(holder); }else{ holder=(ChildHolderOne)convertView.getTag(); } returnconvertView; } classChildHolderOne{ TextViewtvTitle; } }
PullToRefreshGridView
packagecom.example.refreshgridview; importandroid.content.Context; importandroid.util.AttributeSet; importandroid.view.ContextMenu.ContextMenuInfo; importandroid.view.View; importandroid.widget.GridView; publicclassPullToRefreshGridViewextendsPullToRefreshAdapterViewBase<GridView>{ classInternalGridViewextendsGridViewimplementsEmptyViewMethodAccessor{ publicInternalGridView(Contextcontext,AttributeSetattrs){ super(context,attrs); } @Override publicvoidsetEmptyView(ViewemptyView){ PullToRefreshGridView.this.setEmptyView(emptyView); } @Override publicvoidsetEmptyViewInternal(ViewemptyView){ super.setEmptyView(emptyView); } @Override publicContextMenuInfogetContextMenuInfo(){ returnsuper.getContextMenuInfo(); } } publicPullToRefreshGridView(Contextcontext){ super(context); } publicPullToRefreshGridView(Contextcontext,intmode){ super(context,mode); } publicPullToRefreshGridView(Contextcontext,AttributeSetattrs){ super(context,attrs); } @Override protectedfinalGridViewcreateRefreshableView(Contextcontext,AttributeSetattrs){ GridViewgv=newInternalGridView(context,attrs); //UseGeneratedID(fromres/values/ids.xml) gv.setId(R.id.gridview); returngv; } @Override publicContextMenuInfogetContextMenuInfo(){ return((InternalGridView)getRefreshableView()).getContextMenuInfo(); } }
PullToRefreshBase
packagecom.example.refreshgridview; importandroid.content.Context; importandroid.os.Handler; importandroid.util.AttributeSet; importandroid.view.MotionEvent; importandroid.view.View; importandroid.view.ViewConfiguration; importandroid.view.ViewGroup; importandroid.view.animation.AccelerateDecelerateInterpolator; importandroid.view.animation.Interpolator; importandroid.widget.LinearLayout; importandroid.widget.TextView; /** * *@authorzlw */ publicabstractclassPullToRefreshBase<TextendsView>extendsLinearLayout{ finalclassSmoothScrollRunnableimplementsRunnable{ staticfinalintANIMATION_DURATION_MS=190; staticfinalintANIMATION_FPS=1000/60; privatefinalInterpolatorinterpolator; privatefinalintscrollToY; privatefinalintscrollFromY; privatefinalHandlerhandler; privatebooleancontinueRunning=true; privatelongstartTime=-1; privateintcurrentY=-1; publicSmoothScrollRunnable(Handlerhandler,intfromY,inttoY){ this.handler=handler; this.scrollFromY=fromY; this.scrollToY=toY; this.interpolator=newAccelerateDecelerateInterpolator(); } @Override publicvoidrun(){ /** *OnlysetstartTimeifthisisthefirsttimewe'restarting,else *actuallycalculatetheYdelta */ if(startTime==-1){ startTime=System.currentTimeMillis(); }else{ /** *Wedodoallcalculationsinlongtoreducesoftwarefloat *calculations.Weuse1000asitgivesusgoodaccuracyand *smallroundingerrors */ longnormalizedTime=(1000*(System.currentTimeMillis()-startTime)) /ANIMATION_DURATION_MS; normalizedTime=Math.max(Math.min(normalizedTime,1000),0); finalintdeltaY=Math .round((scrollFromY-scrollToY) *interpolator .getInterpolation(normalizedTime/1000f)); this.currentY=scrollFromY-deltaY; setHeaderScroll(currentY); } //Ifwe'renotatthetargetY,keepgoing... if(continueRunning&&scrollToY!=currentY){ handler.postDelayed(this,ANIMATION_FPS); } } publicvoidstop(){ this.continueRunning=false; this.handler.removeCallbacks(this); } }; //=========================================================== //Constants //=========================================================== staticfinalfloatFRICTION=2.0f; staticfinalintPULL_TO_REFRESH=0x0; staticfinalintRELEASE_TO_REFRESH=0x1; staticfinalintREFRESHING=0x2; staticfinalintMANUAL_REFRESHING=0x3; publicstaticfinalintMODE_PULL_DOWN_TO_REFRESH=0x1; publicstaticfinalintMODE_PULL_UP_TO_REFRESH=0x2; publicstaticfinalintMODE_BOTH=0x3; //=========================================================== //Fields //=========================================================== privateinttouchSlop; privatefloatinitialMotionY; privatefloatlastMotionX; privatefloatlastMotionY; privatebooleanisBeingDragged=false; privateintstate=PULL_TO_REFRESH; privateintmode=MODE_PULL_UP_TO_REFRESH; privateintcurrentMode; privatebooleandisableScrollingWhileRefreshing=true; TrefreshableView; privatebooleanisPullToRefreshEnabled=true; privateLoadingLayoutheaderLayout; privateLoadingLayoutfooterLayout; privateintheaderHeight; privatefinalHandlerhandler=newHandler(); privateOnRefreshListeneronRefreshListener; privateSmoothScrollRunnablecurrentSmoothScrollRunnable; //=========================================================== //Constructors //=========================================================== publicPullToRefreshBase(Contextcontext){ super(context); init(context,null); } publicPullToRefreshBase(Contextcontext,intmode){ super(context); this.mode=mode; init(context,null); } publicPullToRefreshBase(Contextcontext,AttributeSetattrs){ super(context,attrs); init(context,attrs); } //=========================================================== //Getter&Setter //=========================================================== /** *Deprecated.Use{@link#getRefreshableView()}fromnowon. * *@deprecated *@returnTheRefreshableViewwhichiscurrentlywrapped */ publicfinalTgetAdapterView(){ returnrefreshableView; } /** *GettheWrappedRefreshableView.Anythingreturnedherehasalreadybeen *addedtothecontentview. * *@returnTheViewwhichiscurrentlywrapped */ publicfinalTgetRefreshableView(){ returnrefreshableView; } /** *WhetherPull-to-Refreshisenabled * *@returnenabled */ publicfinalbooleanisPullToRefreshEnabled(){ returnisPullToRefreshEnabled; } /** *ReturnswhetherthewidgethasdisabledscrollingontheRefreshableView *whilerefreshing. * *@returntrueifthewidgethasdisabledscrollingwhilerefreshing */ publicfinalbooleanisDisableScrollingWhileRefreshing(){ returndisableScrollingWhileRefreshing; } /** *ReturnswhethertheWidgetiscurrentlyintheRefreshingstate * *@returntrueiftheWidgetiscurrentlyrefreshing */ publicfinalbooleanisRefreshing(){ returnstate==REFRESHING||state==MANUAL_REFRESHING; } /** *BydefaulttheWidgetdisabledscrollingontheRefreshableViewwhile *refreshing.Thismethodcanchangethisbehaviour. * *@paramdisableScrollingWhileRefreshing *-trueifyouwanttodisablescrollingwhilerefreshing */ publicfinalvoidsetDisableScrollingWhileRefreshing( booleandisableScrollingWhileRefreshing){ this.disableScrollingWhileRefreshing=disableScrollingWhileRefreshing; } /** *MarkthecurrentRefreshascomplete.WillResettheUIandhidethe *RefreshingView */ publicfinalvoidonRefreshComplete(){ if(state!=PULL_TO_REFRESH){ resetHeader(); if(onShowLayoutListener!=null){ onShowLayoutListener.onDismiss(); } } } /** *SetOnRefreshListenerfortheWidget * *@paramlistener *-ListenertobeusedwhentheWidgetissettoRefresh */ publicfinalvoidsetOnRefreshListener(OnRefreshListenerlistener){ onRefreshListener=listener; } /** *autoloadheaderLayouttorefresh * *@paramlistener */ publicfinalvoidsetFirstAutoPullUpToRefresh(OnRefreshListenerlistener){ setRefreshingInternal(true,MODE_PULL_DOWN_TO_REFRESH); listener.onRefresh(MODE_PULL_DOWN_TO_REFRESH); } /** *setrefreshLable,defaultusenull * *@parampullLabel *@paramreleaseLabel *@paramrefreshingLabel */ publicvoidsetRefreshLabel(StringpullLabel,StringreleaseLabel, StringrefreshingLabel){ if(pullLabel!=null){ setPullLabel(pullLabel); } if(releaseLabel!=null){ setReleaseLabel(releaseLabel); } if(refreshingLabel!=null){ setRefreshingLabel(refreshingLabel); } } /** *Amutatortoenable/disablePull-to-RefreshforthecurrentView * *@paramenable *WhetherPull-To-Refreshshouldbeused */ publicfinalvoidsetPullToRefreshEnabled(booleanenable){ this.isPullToRefreshEnabled=enable; } /** *SetTexttoshowwhentheWidgetisbeingpulled,andwillrefreshwhen *released * *@paramreleaseLabel *-Stringtodisplay */ privatevoidsetReleaseLabel(StringreleaseLabel){ if(null!=headerLayout){ headerLayout.setReleaseLabel(releaseLabel); } if(null!=footerLayout){ footerLayout.setReleaseLabel(releaseLabel); } } /** *SetTexttoshowwhentheWidgetisbeingPulled * *@parampullLabel *-Stringtodisplay */ privatevoidsetPullLabel(StringpullLabel){ if(null!=headerLayout){ headerLayout.setPullLabel(pullLabel); } if(null!=footerLayout){ footerLayout.setPullLabel(pullLabel); } } /** *SetTexttoshowwhentheWidgetisrefreshing * *@paramrefreshingLabel *-Stringtodisplay */ privatevoidsetRefreshingLabel(StringrefreshingLabel){ if(null!=headerLayout){ headerLayout.setRefreshingLabel(refreshingLabel); } if(null!=footerLayout){ footerLayout.setRefreshingLabel(refreshingLabel); } } publicfinalvoidsetRefreshing(){ this.setRefreshing(true); } /** *SetstheWidgettobeintherefreshstate.TheUIwillbeupdatedto *showthe'Refreshing'view. * *@paramdoScroll *-trueifyouwanttoforceascrolltotheRefreshingview. */ publicfinalvoidsetRefreshing(booleandoScroll){ if(!isRefreshing()){ setRefreshingInternal(doScroll); state=MANUAL_REFRESHING; } } publicfinalbooleanhasPullFromTop(){ returncurrentMode!=MODE_PULL_UP_TO_REFRESH; } //=========================================================== //Methodsfor/fromSuperClass/Interfaces //=========================================================== @Override publicfinalbooleanonTouchEvent(MotionEventevent){ if(!isPullToRefreshEnabled){ returnfalse; } if(isRefreshing()&&disableScrollingWhileRefreshing){ returntrue; } if(event.getAction()==MotionEvent.ACTION_DOWN &&event.getEdgeFlags()!=0){ returnfalse; } switch(event.getAction()){ caseMotionEvent.ACTION_MOVE:{ if(isBeingDragged){ if(Math.abs(event.getY()-downLocation)>5 &&onShowLayoutListener!=null){ onShowLayoutListener.onShow(); } lastMotionY=event.getY(); this.pullEvent(); returntrue; } break; } caseMotionEvent.ACTION_DOWN:{ if(isReadyForPull()){ downLocation=event.getY(); lastMotionY=initialMotionY=event.getY(); returntrue; } break; } caseMotionEvent.ACTION_CANCEL: caseMotionEvent.ACTION_UP:{ if(isBeingDragged){ isBeingDragged=false; if(state==RELEASE_TO_REFRESH&&null!=onRefreshListener){ setRefreshingInternal(true); onRefreshListener.onRefresh(currentMode); }else{ smoothScrollTo(0); if(onShowLayoutListener!=null){ onShowLayoutListener.onDismiss(); } } returntrue; } break; } } returnfalse; } //remebertodownlocation privatefloatdownLocation=0; @Override publicfinalbooleanonInterceptTouchEvent(MotionEventevent){ if(!isPullToRefreshEnabled){ returnfalse; } if(isRefreshing()&&disableScrollingWhileRefreshing){ returntrue; } finalintaction=event.getAction(); if(action==MotionEvent.ACTION_CANCEL ||action==MotionEvent.ACTION_UP){ isBeingDragged=false; returnfalse; } if(action!=MotionEvent.ACTION_DOWN&&isBeingDragged){ returntrue; } switch(action){ caseMotionEvent.ACTION_MOVE:{ if(isReadyForPull()){ finalfloaty=event.getY(); finalfloatdy=y-lastMotionY; finalfloatyDiff=Math.abs(dy); finalfloatxDiff=Math.abs(event.getX()-lastMotionX); if(yDiff>touchSlop&&yDiff>xDiff){ if((mode==MODE_PULL_DOWN_TO_REFRESH||mode==MODE_BOTH) &&dy>=0.0001f&&isReadyForPullDown()){ lastMotionY=y; isBeingDragged=true; if(mode==MODE_BOTH){ currentMode=MODE_PULL_DOWN_TO_REFRESH; } }elseif((mode==MODE_PULL_UP_TO_REFRESH||mode==MODE_BOTH) &&dy<=0.0001f&&isReadyForPullUp()){ lastMotionY=y; isBeingDragged=true; if(mode==MODE_BOTH){ currentMode=MODE_PULL_UP_TO_REFRESH; } } } } break; } caseMotionEvent.ACTION_DOWN:{ if(isReadyForPull()){ lastMotionY=initialMotionY=event.getY(); lastMotionX=event.getX(); isBeingDragged=false; } break; } caseMotionEvent.ACTION_UP: break; } setRefreshLabel(currentMode); returnisBeingDragged; } protectedvoidaddRefreshableView(Contextcontext,TrefreshableView){ addView(refreshableView,newLinearLayout.LayoutParams( LayoutParams.FILL_PARENT,0,1.0f)); } /** *ThisisimplementedbyderivedclassestoreturnthecreatedView.Ifyou *needtouseacustomView(suchasacustomListView),overridethis *methodandreturnaninstanceofyourcustomclass. * *BesuretosettheIDoftheviewinthismethod,especiallyifyou're *usingaListActivityorListFragment. * *@paramcontext *@paramattrs *AttributeSetfromwrappedclass.Meansthatanythingyou *includeintheXMLlayoutdeclarationwillberoutedtothe *createdView *@returnNewinstanceoftheRefreshableView */ protectedabstractTcreateRefreshableView(Contextcontext, AttributeSetattrs); publicfinalintgetCurrentMode(){ returncurrentMode; } protectedfinalLoadingLayoutgetFooterLayout(){ returnfooterLayout; } protectedfinalLoadingLayoutgetHeaderLayout(){ returnheaderLayout; } protectedfinalintgetHeaderHeight(){ returnheaderHeight; } protectedfinalintgetMode(){ returnmode; } /** *ImplementedbyderivedclasstoreturnwhethertheViewisinastate *wheretheusercanPulltoRefreshbyscrollingdown. * *@returntrueiftheViewiscurrentlythecorrectstate(forexample,top *ofaListView) */ protectedabstractbooleanisReadyForPullDown(); /** *ImplementedbyderivedclasstoreturnwhethertheViewisinastate *wheretheusercanPulltoRefreshbyscrollingup. * *@returntrueiftheViewiscurrentlyinthecorrectstate(forexample, *bottomofaListView) */ protectedabstractbooleanisReadyForPullUp(); //=========================================================== //Methods //=========================================================== protectedvoidresetHeader(){ state=PULL_TO_REFRESH; isBeingDragged=false; if(null!=headerLayout){ headerLayout.reset(); } if(null!=footerLayout){ footerLayout.reset(); } smoothScrollTo(0); } /** *unlessspecialrequirementstocallthemethod,defaultcallthemethod *{@link#setRefreshingInternal(booleandoScroll)} * *@paramdoScroll *@parammode */ protectedvoidsetRefreshingInternal(booleandoScroll,intmode){ state=REFRESHING; setRefreshLabel(mode); if(null!=headerLayout){ headerLayout.refreshing(); } if(doScroll){ smoothScrollTo(mode==MODE_PULL_DOWN_TO_REFRESH?-headerHeight :headerHeight); } } /** *setlastrefreshtime * *@paramtime */ publicvoidsetRefreshTime(Stringtime){ TextViewmHeaderTimeView=(TextView)headerLayout .findViewById(R.id.xlistview_header_time); mHeaderTimeView.setText(time); } publicvoidsetRefreshTime(longtime){ TextViewmHeaderTimeView=(TextView)headerLayout .findViewById(R.id.xlistview_header_time); mHeaderTimeView.setText(TimeUtil.getChatTime(time)); } protectedvoidsetRefreshingInternal(booleandoScroll){ state=REFRESHING; setRefreshLabel(currentMode); if(null!=footerLayout){ footerLayout.refreshing(); } if(null!=headerLayout){ headerLayout.refreshing(); } if(doScroll){ smoothScrollTo(currentMode==MODE_PULL_DOWN_TO_REFRESH?-headerHeight :headerHeight); } } privatevoidsetRefreshLabel(intmode){ if(mode==MODE_PULL_DOWN_TO_REFRESH){ setRefreshLabel("涓嬫媺鍒锋柊","閲婃斁绔嬪嵆鍒锋柊","姝e湪鍒锋柊"); } if(mode==MODE_PULL_UP_TO_REFRESH){ setRefreshLabel("涓婃媺鑾峰彇鏇村","鏉惧紑鏄剧ず鏇村","姝e湪鍔犺浇"); } } protectedfinalvoidsetHeaderScroll(inty){ scrollTo(0,y); } protectedfinalvoidsmoothScrollTo(inty){ if(null!=currentSmoothScrollRunnable){ currentSmoothScrollRunnable.stop(); } if(this.getScrollY()!=y){ this.currentSmoothScrollRunnable=newSmoothScrollRunnable( handler,getScrollY(),y); handler.post(currentSmoothScrollRunnable); } } publicvoidinit(intmode){ //LoadingViewStrings StringpullLabel=context .getString(R.string.pull_to_refresh_pull_label); StringrefreshingLabel=context .getString(R.string.pull_to_refresh_refreshing_label); StringreleaseLabel=context .getString(R.string.pull_to_refresh_release_label); //AddLoadingViews if(mode==MODE_PULL_DOWN_TO_REFRESH||mode==MODE_BOTH){ headerLayout=newLoadingLayout(context,MODE_PULL_DOWN_TO_REFRESH,releaseLabel,pullLabel,refreshingLabel); addView(headerLayout,0,newLinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT)); measureView(headerLayout); headerHeight=headerLayout.getMeasuredHeight(); } if(mode==MODE_PULL_UP_TO_REFRESH||mode==MODE_BOTH){ footerLayout=newLoadingLayout(context,MODE_PULL_UP_TO_REFRESH,releaseLabel,pullLabel,refreshingLabel); addView(footerLayout,newLinearLayout.LayoutParams( ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); measureView(footerLayout); headerHeight=footerLayout.getMeasuredHeight(); } //StyleablesfromXML if(null!=headerLayout){ //headerLayout.setTextColor(Color.BLACK); } if(null!=footerLayout){ //footerLayout.setTextColor(Color.BLACK); } //HideLoadingViews switch(mode){ caseMODE_BOTH: setPadding(0,-headerHeight,0,-headerHeight); break; caseMODE_PULL_UP_TO_REFRESH: setPadding(0,0,0,-headerHeight); break; caseMODE_PULL_DOWN_TO_REFRESH: default: setPadding(0,-headerHeight,0,0); break; } //Ifwe'renotusingMODE_BOTH,thenjustsetcurrentModetocurrent //mode if(mode!=MODE_BOTH){ currentMode=mode; } this.mode=mode; } privatevoidinit(Contextcontext,AttributeSetattrs){ this.context=context; setOrientation(LinearLayout.VERTICAL); touchSlop=ViewConfiguration.getTouchSlop(); //RefreshableView //Bypassingtheattrs,wecanaddListView/GridViewparamsviaXML refreshableView=this.createRefreshableView(context,attrs); this.addRefreshableView(context,refreshableView); } privateContextcontext; 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; intchildHeightSpec; if(lpHeight>0){ childHeightSpec=MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY); }else{ childHeightSpec=MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); } child.measure(childWidthSpec,childHeightSpec); } /** *ActionsaPullEvent * *@returntrueiftheEventhasbeenhandled,falseiftherehasbeenno *change */ privatebooleanpullEvent(){ finalintnewHeight; finalintoldHeight=this.getScrollY(); switch(currentMode){ caseMODE_PULL_UP_TO_REFRESH: newHeight=Math.round(Math.max(initialMotionY-lastMotionY,0) /FRICTION); //newHeight=Math.round((initialMotionY-lastMotionY)/ //FRICTION); break; caseMODE_PULL_DOWN_TO_REFRESH: default: newHeight=Math.round(Math.min(initialMotionY-lastMotionY,0) /FRICTION); //newHeight=Math.round((initialMotionY-lastMotionY)/ //FRICTION); break; } setHeaderScroll(newHeight); if(newHeight!=0){ if(state==PULL_TO_REFRESH&&headerHeight<Math.abs(newHeight)){ state=RELEASE_TO_REFRESH; switch(currentMode){ caseMODE_PULL_UP_TO_REFRESH: footerLayout.releaseToRefresh(); break; caseMODE_PULL_DOWN_TO_REFRESH: headerLayout.releaseToRefresh(); break; } returntrue; }elseif(state==RELEASE_TO_REFRESH &&headerHeight>=Math.abs(newHeight)){ state=PULL_TO_REFRESH; switch(currentMode){ caseMODE_PULL_UP_TO_REFRESH: footerLayout.pullToRefresh(); break; caseMODE_PULL_DOWN_TO_REFRESH: headerLayout.pullToRefresh(); break; } returntrue; } } returnoldHeight!=newHeight; } privatebooleanisReadyForPull(){ switch(mode){ caseMODE_PULL_DOWN_TO_REFRESH: returnisReadyForPullDown(); caseMODE_PULL_UP_TO_REFRESH: returnisReadyForPullUp(); caseMODE_BOTH: returnisReadyForPullUp()||isReadyForPullDown(); } returnfalse; } //=========================================================== //InnerandAnonymousClasses //=========================================================== publicstaticinterfaceOnRefreshListener{ publicvoidonRefresh(intmode); } privateOnShowLayoutListeneronShowLayoutListener; publicvoidsetOnShowLayoutListener(OnShowLayoutListenerlistener){ this.onShowLayoutListener=listener; } publicstaticinterfaceOnShowLayoutListener{ /** *鏄鍚︽e湪鏄剧ず搴曢儴甯冨眬 */ publicvoidonShow(); /** *鏄鍚︽秷澶 */ publicvoidonDismiss(); } publicstaticinterfaceOnLastItemVisibleListener{ publicvoidonLastItemVisible(); } @Override publicvoidsetLongClickable(booleanlongClickable){ getRefreshableView().setLongClickable(longClickable); } }
主要代码都在上面贴出来了,当然还是一定要有demo
DEMO源码下载
这个源码里面我把PullToRefreshExpandableListView和PullToRefreshListView也都放进来了,一样的逻辑。希望对大家有用。如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!