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);
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。