Android-自定义控件之ListView下拉刷新的实现
自定义控件学了很久了,发现学了总是忘,于是打算用博客来记录自己学习的知识点。
今天是自定义ListView来实现下拉刷新,这些文章都是借鉴慕课网上的视频来写的.
自定义一个控件,先是看它继承于那个控件,如果我们继承View控件的话,那得让我们写很多关于ListView的功能,这些东西我自己觉得很麻烦,而且也没有那个必要因为我们可以直接继承ListView,在listView的基础上来加一些我们需要的东西。
1.向ListView加Header布局
privatevoidinitView(Contextcontext) { mLayoutInflater=LayoutInflater.from(context); mHeaerView=mLayoutInflater.inflate(R.layout.header_layout,null,false); addHeaderView(mHeaerView); }
2.隐藏Header布局
privatevoidinitView(Contextcontext){ mLayoutInflater=LayoutInflater.from(context); mHeaerView=mLayoutInflater.inflate(R.layout.header_layout,null,false); measureView(mHeaerView); mHeaderViewHeight=mHeaerView.getMeasuredHeight(); setHeaderViewHeightPadding(mHeaderViewHeight); Log.i("main",mHeaderViewHeight+""); addHeaderView(mHeaerView); } privatevoidmeasureView(Viewview) { ViewGroup.LayoutParamslp=view.getLayoutParams(); if(lp==null) { lp=newViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT); } //mHeaerView.measure(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT); /** *width和height里面包含的不仅仅有View的宽和高,还有View控件的测量模式 *测量模式的产生方式就是如下所示 */ intwidth=ViewGroup.getChildMeasureSpec(0,0,lp.width); intheight=0; inttempHeight=lp.height; if(tempHeight>0) { height=MeasureSpec.makeMeasureSpec(tempHeight,MeasureSpec.EXACTLY); } view.measure(width,height); } privatevoidsetHeaderViewHeightPadding(intpadding){ mHeaerView.setPadding(mHeaerView.getPaddingLeft(),-padding,mHeaerView.getPaddingRight(),mHeaerView.getPaddingBottom()); mHeaerView.invalidate(); }
3.实现ListView的下拉刷新(一)
要想实现ListView的下拉刷新,必须监听ListView是否滑动到最顶端,因此要实现ListView的监听接口OnScrollListener,并且要监听ListView的OnTouch事件。根据滑动的情况来判断刷新的情况。
首先我们在定义了一个成员变量来保存ListView的状态--mState
其次定义了几个静态常量来表示不同的状态
privatefinalstaticintNONE=0;//无状态 privatefinalstaticintDOWN_UPDATE=1;//提示下拉可以刷新 privatefinalstaticintUPDATE=2;//提示松开可以刷新 privatefinalstaticintREFLASH=3;//更新
最后则是根据不同的滑动来更改mState的状态
@Override publicbooleanonTouchEvent(MotionEventev){ switch(ev.getAction()){ caseMotionEvent.ACTION_DOWN:{ if(mFirstVisibleItem==0){ mIsRemark=true;//mIsRemark只是一个标记,表示当前可见的第一个Item是不是所有的Item中的第一个 mStartY=(int)ev.getY(); Log.i("main","我进来了"); } break; } caseMotionEvent.ACTION_MOVE:{ onMove(ev); tempY=(int)(ev.getY()-mStartY); Log.i("main","tempY="+tempY); break; } caseMotionEvent.ACTION_UP:{ if(mState==DOWN_UPDATE) { mState=NONE; } if(mState==UPDATE) { mState=REFLASH; mListener.reFlash(); Log.i("main","我来了"); } Log.i("main","tempY11="+tempY); if(tempY<=0&&mIsRemark) { Log.i("main","我进来le"); mState=NONE; } change(); break; } } returnsuper.onTouchEvent(ev); } privatevoidonMove(MotionEventev){ if(mIsRemark){ if(ev.getY()-mStartY>0){ intdy=(int)(ev.getY()-mStartY); if(dy>mHeaderViewHeight+20){ mState=UPDATE; }else{ mState=DOWN_UPDATE; } setHeaderViewHeightPadding(mHeaderViewHeight-dy); change(); } return; } return; } /** *change方法主要是用来处理不同状态下的事件 * */ privatevoidchange(){ initChildView(); RotateAnimationani=newRotateAnimation(0,180,RotateAnimation.RELATIVE_TO_SELF,0.5f,RotateAnimation.RELATIVE_TO_SELF,0.5f); ani.setDuration(500); ani.setFillAfter(true); RotateAnimationani1=newRotateAnimation(180,0,RotateAnimation.RELATIVE_TO_SELF,0.5f,RotateAnimation.RELATIVE_TO_SELF,0.5f); ani1.setDuration(500); ani1.setFillAfter(true); if(mState==UPDATE) { mProgressBar.setVisibility(View.GONE); mImageView.setVisibility(View.VISIBLE); mImageView.clearAnimation(); mImageView.setAnimation(ani); mTextViewFlash.setText("松开可以刷新!"); mTextViewTime.setVisibility(View.VISIBLE); mTextViewTime.setText("上次更新的时间:"+mUpdateTime); } if(mState==DOWN_UPDATE) { mProgressBar.setVisibility(View.GONE); mImageView.setVisibility(View.VISIBLE); mTextViewTime.setVisibility(View.VISIBLE); mImageView.clearAnimation(); mImageView.setAnimation(ani1); mTextViewFlash.setText("下拉可以刷新"); mTextViewTime.setText("上次更新的时间:"+mUpdateTime); } if(mState==REFLASH) { setHeaderViewHeightPadding(10); mProgressBar.setVisibility(View.VISIBLE); mImageView.setVisibility(View.GONE); mTextViewTime.setVisibility(View.GONE); mTextViewFlash.setText("正在刷新..."); mImageView.clearAnimation(); } if(mState==NONE) { Log.i("main","workspace"); setHeaderViewHeightPadding(mHeaderViewHeight); mIsRemark=false; mProgressBar.setVisibility(View.GONE); mImageView.setVisibility(View.VISIBLE); mImageView.setAnimation(ani1); } } privatevoidinitChildView() { if(mTextViewFlash==null) { mTextViewFlash=(TextView)mHeaerView.findViewById(R.id.id_textView_Flash); } if(mTextViewTime==null) { mTextViewTime=(TextView)mHeaerView.findViewById(R.id.id_textView_Time); } if(mImageView==null) { mImageView=(ImageView)mHeaerView.findViewById(R.id.id_imagView); } if(mProgressBar==null) { mProgressBar=(ProgressBar)mHeaerView.findViewById(R.id.id_progressbar); } }
4.实现ListView的下拉刷新(二)
经过上面的过程,是可以下拉的,处理不同状态下的事件。还有一个问题就是刷新,也就是加载新的数据。加载刷新的操作肯定必须在UI线程中,因此ListView中必须得有一个回调接口,用来MinaActivity来实现,并且来进行一些操作。
回调接口:
publicvoidsetOnFlashListener(FlashListenerlistener) { this.mListener=listener; } publicinterfaceFlashListener { voidreFlash(); }
回调接口的调用:
if(mState==UPDATE) { mState=REFLASH; mListener.reFlash(); Log.i("main","我来了"); }
MainActivity中回调接口的实现和接口方法的实现:
mListView.setOnFlashListener(newFlashListView.FlashListener(){ @Override publicvoidreFlash(){ Handlerhandler=newHandler(); handler.postDelayed(newRunnable(){ @Override publicvoidrun(){ addDatas(); loadDatas(); mListView.reFalshComplete(); } },5000); } }); privatevoidaddDatas() { inti=mDatas.size(); for(intj=i;j<i+10;j++) { mDatas.add(newBean("Title"+j,"Content"+j,R.mipmap.ic_launcher)); } myAdapter.dataChange(mDatas); } privatevoidloadDatas() { mListView.setAdapter(myAdapter); }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。