Android仿XListView支持下拉刷新和上划加载更多的自定义RecyclerView

Android仿XListView支持下拉刷新和上划加载更多的自定义RecyclerView,第1张

概述首先给大家展示下效果图,感觉还不错,请继续往下阅读:下拉刷新:    

首先给大家展示下效果图,感觉还不错,请继续往下阅读:

下拉刷新:

      



上划加载

      


在项目更新的过程中,遇到了一个将XListVIEw换成recyclerVIEw的需求,而且更换完之后大体效果不能变,但是对于下拉刷新这样的效果,谷歌给出的解决方案是把RecyclerVIEw放在一个SwipeRefreshLayout中,但是这样其实是拉下一个小圆形控件实现的,和XListVIEw的header效果不同。在网上找了很多的别人代码,都没有实现我想要的效果,于是自己动手写了一个。

具体实现的效果有以下几条

下拉刷新功能:

1、实现一个有d性的拖出效果:思路参考XListVIEw,recyclerVIEw的position=0的位置放一个header布局,这个布局的margin top默认为负的布局高度,所以这块布局就一直处于屏幕外部,在下拉的时候通过ontouchListener根据手指的移动动态修改margin top,慢慢的拖出,当拖出的距离也就是margin top变为正数以后,就盖面header布局的状态,改变箭头的方向并改变提示语

2、实现有d性的回d效果:用timerTask写了一个动态修改的header布局的margin top的动画,每隔一定的时间减小margin top的值,当用户松手的时候通过一个函数updateheaderHeight()来执行这个动画。

3、实现用户非手动拖拉的自动刷新效果:这个recyclerVIEw还有一个方法叫forceRefresh(),就是不需要用户手动下拉,头部自己滚动出来,然后刷新完再自己收回去,自动下拉也是用一个timerTask每隔十几毫秒增加margin top的值让头部慢慢露出来

上划加载更多功能:

1、实现滚动到底部自动停住效果: 有时候recyclerVIEw滚动太快,滚到底部的时候会根据惯性向上飘,这个地方到底的时候监控recyclerVIEw滚动速度,如果非常快说明是惯性滚动,就不修改footer布局的高度

2、实现向上拖动效果:复写了recyclerVIEw的onScrollListener,在手指向上滚动的时候,通过updateFooterHeight()方法动态修改底部footerVIEw的margin bottom,同headerVIEw一样,在手指移动的时候让这个margin跟着变大,以增加footer布局的高度,而且手指移动的越网上,增加的margin的高度就越小,实现一个有d性的上拉效果,防止误 *** 作。

3、实现自动回d的效果:通过监控footer布局的margin bottom来确定松手的时候是否需要开始刷新,如果margin bottom大于某个值得时候就修改footer布局的状态从normal变成ready,在ready状态下松手就开始刷新 *** 作,回d也像header布局一样通过一个timerTask每隔十几毫秒修改margin的大小来实现回d效果

注意事项:

1、为了实现头部和底部的代码分离,头部用的是ontouchListener,底部用的是onScrollListener

2、本recyclerVIEw里面已经内置了一个layoutManager,所以不要给recyclerVIEw再设置layoutManager,否则会出现头部不出来,下拉报空指针的情况,底部出现但是滑动没有效果

3、这个recyclerVIEw内置了一个抽象类作为adapter,请继承这个内置的AlxDragRecyclerVIEwAdapter使用,或者按照这里面的逻辑重新写adapter

有其他的问题欢迎问我

4、一些常用的功能,比如设置该控件是否能够支持下拉加载和上拉刷新,等等API接口,请直接参考XListVIEw的用法即可

使用方法:

继承AlxDragRecyclerVIEwAdapter写一个adapter,然后写两个类分别实现OnRefreshListener和LoadMoreListener,把具体的刷新逻辑写在里面,在准备好显示数据后调用adapter的notifyDataSetChanged()方法或notifyItemInserted()方法,并执行该recyclerVIEw的stopLoadmore()方法和stopRefresh()方法。

下面是代码,这个控件有很多的内部类,包括头部,底部的布局控件(CustomDragheaderVIEw,CustomDragFooterVIEw),adapter,layoutmanager都已经以内部类的方式集成在里面,减少迁移时候的复杂度

import androID.content.Context;import androID.graphics.color;import androID.os.Handler;import androID.support.v7.Widget.linearlayoutmanager;import androID.support.v7.Widget.RecyclerVIEw;import androID.util.AttributeSet;import androID.util.Log;import androID.vIEw.LayoutInflater;import androID.vIEw.MotionEvent;import androID.vIEw.VIEw;import androID.vIEw.VIEwGroup;import androID.vIEw.WindowManager;import androID.vIEw.animation.Animation;import androID.vIEw.animation.RotateAnimation;import androID.Widget.ImageVIEw;import androID.Widget.linearLayout;import androID.Widget.TextVIEw;import com.xxx.app.R;import java.util.List;import java.util.Timer;import java.util.TimerTask;/** * Created by Alex on 2016/1/27. */public class AlxRefreshLoadMoreRecyclerVIEw extends RecyclerVIEw { private int footerHeight = -1; linearlayoutmanager layoutManager; // -- footer vIEw private CustomDragRecyclerFooterVIEw mFooterVIEw; private boolean mEnablePullLoad; private boolean mpullLoading; private boolean isBottom; private boolean mIsFooterReady = false; private LoadMoreListener loadMoreListener; // -- header vIEw private CustomDragheaderVIEw mheaderVIEw; private boolean mEnablePullRefresh = true; private boolean mIsRefreshing; private boolean isheader; private boolean mIsheaderReady = false; private Timer timer; private float oldY; Handler handler = new Handler(); private OnRefreshListener refreshListener; private AlxDragRecyclerVIEwAdapter adapter; private int maxpullHeight = 50;//最多下拉高度的px值 private static final int header_HEIGHT = 68;//头部高度68dp private static final int MAX_PulL_LENGTH = 150;//最多下拉150dp private OnClickListener footerClickListener; public AlxRefreshLoadMoreRecyclerVIEw(Context context) {  super(context);  initVIEw(context); } public AlxRefreshLoadMoreRecyclerVIEw(Context context,AttributeSet attrs) {  super(context,attrs);  initVIEw(context); } public AlxRefreshLoadMoreRecyclerVIEw(Context context,AttributeSet attrs,int defStyle) {  super(context,attrs,defStyle);  initVIEw(context); } public voID setAdapter(AlxDragRecyclerVIEwAdapter adapter){  super.setAdapter(adapter);  this.adapter = adapter; } public boolean ismpullLoading() {  return mpullLoading; } public boolean ismIsRefreshing() {  return mIsRefreshing; } private voID updateFooterHeight(float delta) {  if(mFooterVIEw==null)return;  int bottommargin = mFooterVIEw.getBottommargin();//  Log.i("Alex3","初始delta是"+delta);  if(delta>50)delta = delta/6;  if(delta>0) {//越往下滑越难滑   if(bottommargin>maxpullHeight)delta = delta*0.65f;   else if(bottommargin>maxpullHeight * 0.83333f)delta = delta*0.7f;   else if(bottommargin>maxpullHeight * 0.66667f)delta = delta*0.75f;   else if(bottommargin>maxpullHeight >> 1)delta = delta*0.8f;   else if(bottommargin>maxpullHeight * 0.33333f)delta = delta*0.85f;   else if(bottommargin>maxpullHeight * 0.16667F && delta > 20)delta = delta*0.2f;//如果是因为惯性向下迅速的俯冲   else if(bottommargin>maxpullHeight * 0.16667F)delta = delta*0.9f;//   Log.i("Alex3","bottommargin是"+mFooterVIEw.getBottommargin()+" delta是"+delta);  }  int height = mFooterVIEw.getBottommargin() + (int) (delta+0.5);  if (mEnablePullLoad && !mpullLoading) {   if (height > 150){//必须拉超过一定距离才加载更多//   if (height > 1){//立即刷新    mFooterVIEw.setState(CustomDragRecyclerFooterVIEw.STATE_READY);    mIsFooterReady = true;//    Log.i("Alex2","ready");   } else {    mFooterVIEw.setState(CustomDragRecyclerFooterVIEw.STATE_norMAL);    mIsFooterReady = false;//    Log.i("Alex2","nomal");   }  }  mFooterVIEw.setBottommargin(height); } private voID resetFooterHeight() {  int bottommargin = mFooterVIEw.getBottommargin();  if (bottommargin > 20) {   Log.i("Alex2","准备重置高度,margin是" + bottommargin + "自高是" + footerHeight);   this.smoothScrollBy(0,-bottommargin);   //一松手就立即开始加载   if(mIsFooterReady){    startLoadMore();   }  } } public voID setLoadMoreListener(LoadMoreListener Listener){  this.loadMoreListener = Listener; } public voID initVIEw(Context context){  layoutManager = new linearlayoutmanager(context);//自带layoutManager,请勿设置  layoutManager.setorIEntation(linearlayoutmanager.VERTICAL);  WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);  int height = wm.getDefaultdisplay().getHeight();  layoutManager.offsetChildrenVertical(height*2);//预加载2/3的卡片  this.setLayoutManager(layoutManager);//  Log.i("Alex","屏幕密度为" + getContext().getResources().getdisplayMetrics().density);  maxpullHeight = dp2px(getContext().getResources().getdisplayMetrics().density,MAX_PulL_LENGTH);//最多下拉150dp  this.footerClickListener = new footerVIEwClickListener();  this.addOnScrollListener(new RecyclerVIEw.OnScrollListener() {   @OverrIDe   public voID onScrollStateChanged(RecyclerVIEw recyclerVIEw,int newState) {    super.onScrollStateChanged(recyclerVIEw,newState);    switch (newState){     case RecyclerVIEw.SCRolL_STATE_IDLE://      Log.i("Alex2","停下了||放手了");      if(isBottom)resetFooterHeight();      break;     case RecyclerVIEw.SCRolL_STATE_DRAGGING://      Log.i("Alex2","开始拖了,现在margin是" + (mFooterVIEw == null ? "" : mFooterVIEw.getBottommargin()));      break;     case RecyclerVIEw.SCRolL_STATE_SETTliNG://      Log.i("Alex2","开始惯性移动");      break;    }   }   @OverrIDe   public voID onScrolled(RecyclerVIEw recyclerVIEw,int dx,int dy) {    super.onScrolled(recyclerVIEw,dx,dy);    int lastItemposition = layoutManager.findLastVisibleItemposition();//    Log.i("Alex2","mEnable是"+mEnablePullLoad+"lastitemposition是"+lastItemposition+" itemcount是"+layoutManager.getItemCount());    if(lastItemposition == layoutManager.getItemCount()-1 && mEnablePullLoad) {//如果到了最后一个     isBottom = true;     mFooterVIEw = (CustomDragRecyclerFooterVIEw)layoutManager.findVIEwByposition(layoutManager.findLastVisibleItemposition());//一开始还不能hIDe,因为hIDe得到最后一个可见的就不是footervIEw了//     Log.i("Alex2","到底啦!!"+"mfooterVIEw是"+mFooterVIEw);     if(mFooterVIEw!=null) mFooterVIEw.setonClickListener(footerClickListener);     if(footerHeight==-1 && mFooterVIEw!=null){      mFooterVIEw.show();      mFooterVIEw.setState(CustomDragRecyclerFooterVIEw.STATE_norMAL);      footerHeight = mFooterVIEw.getMeasuredHeight();//这里的测量一般不会出问题//      Log.i("Alex2","底部高度为" + footerHeight);     }     updateFooterHeight(dy);    }else if(lastItemposition == layoutManager.getItemCount()-1 && mEnablePullLoad){//如果到了倒数第二个     startLoadMore();//开始加载更多    }    else {     isBottom = false;    }   }  }); } /**  * 设置是否开启上拉加载更多的功能  *  * @param enable  */ public voID setPullLoadEnable(boolean enable) {  mpullLoading = false;  mEnablePullLoad = enable;  if(adapter!=null)adapter.setPullLoadMoreEnable(enable);//adapter和recyclerVIEw要同时设置  if(mFooterVIEw==null)return;  if (!mEnablePullLoad) {//   this.smoothScrollBy(0,-footerHeight);   mFooterVIEw.hIDe();   mFooterVIEw.setonClickListener(null);   mFooterVIEw.setBottommargin(0);   //make sure "pull up" don't show a line in bottom when ListvIEw with one page  } else {   mFooterVIEw.show();   mFooterVIEw.setState(CustomDragRecyclerFooterVIEw.STATE_norMAL);   mFooterVIEw.setVisibility(VISIBLE);   //make sure "pull up" don't show a line in bottom when ListvIEw with one page   // both "pull up" and "click" will invoke load more.   mFooterVIEw.setonClickListener(new OnClickListener() {    @OverrIDe    public voID onClick(VIEw v) {     startLoadMore();    }   });  } } /**  * 停止loadmore  */ public voID stopLoadMore() {  if (mpullLoading == true) {   mpullLoading = false;   if(mFooterVIEw==null)return;   mFooterVIEw.show();   mFooterVIEw.setState(CustomDragRecyclerFooterVIEw.STATE_ERROR);  } } private voID startLoadMore() {  if(mpullLoading)return;  mpullLoading = true;  if(mFooterVIEw!=null)mFooterVIEw.setState(CustomDragRecyclerFooterVIEw.STATE_LOADING);  Log.i("Alex2","现在开始加载");  mIsFooterReady = false;  if (loadMoreListener != null) {   loadMoreListener.onLoadMore();  } } /**  * 在刷新时要执行的方法  */ public interface LoadMoreListener{  public voID onLoadMore(); } /**  * 点击loadMore后要执行的事件  */ class footerVIEwClickListener implements OnClickListener {  @OverrIDe  public voID onClick(VIEw v) {   startLoadMore();  } } private voID updateheaderHeight(float delta) {  mheaderVIEw = (CustomDragheaderVIEw) layoutManager.findVIEwByposition(0);//  Log.i("Alex2","现在在头部!!!! header自高是" + mheaderVIEw.getHeight() + " margin 是" + mheaderVIEw.gettopmargin());//自高一般不会算错//  Log.i("Alex2","正在设置margin" + mheaderVIEw.gettopmargin() +"delta是"+delta);  if(delta>0){//如果是往下拉   int topmargin = mheaderVIEw.gettopmargin();   if(topmargin>maxpullHeight * 0.33333f)delta = delta*0.5f;   else if(topmargin>maxpullHeight * 0.16667F)delta = delta*0.55f;   else if(topmargin>0)delta = delta*0.6f;   else if(topmargin<0)delta = delta*0.6f;//如果没有被完全拖出来   mheaderVIEw.settopmargin(mheaderVIEw.gettopmargin() + (int)delta);  } else{//如果是推回去   if(!mIsRefreshing || mheaderVIEw.gettopmargin()>0) {//在刷新的时候不把margin设为负值以在惯性滑动的时候能滑回去    this.scrollBy(0,(int) delta);//禁止既滚动,又同时减少触摸//    Log.i("Alex2","正在往回推" + delta);    mheaderVIEw.settopmargin(mheaderVIEw.gettopmargin() + (int) delta);   }  }  if(mheaderVIEw.gettopmargin()>0 && !mIsRefreshing){   mIsheaderReady = true;   mheaderVIEw.setState(CustomDragheaderVIEw.STATE_READY);  }//设置为ready状态  else if(!mIsRefreshing){   mIsheaderReady = false;   mheaderVIEw.setState(CustomDragheaderVIEw.STATE_norMAL);  }//设置为普通状态并且缩回去 } @OverrIDe public voID smoothScrollToposition(final int position) {  super.smoothScrollToposition(position);  final Timer scrollTimer = new Timer();  TimerTask timerTask = new TimerTask() {   @OverrIDe   public voID run() {    int bottomCardposition = layoutManager.findLastVisibleItemposition();    if(bottomCardposition<position+1){//如果要向下滚     handler.post(new Runnable() {      @OverrIDe      public voID run() {       smoothScrollBy(0,50);      }     });    }else if(bottomCardposition>position){//如果要向上滚     handler.post(new Runnable() {      @OverrIDe      public voID run() {       smoothScrollBy(0,-50);      }     });    }else {     if(scrollTimer!=null)scrollTimer.cancel();    }   }  };  scrollTimer.schedule(timerTask,20); } /**  * 在用户非手动强制刷新的时候,通过一个动画把头部一点点冒出来  */ private voID smoothShowheader(){  if(mheaderVIEw==null)return;//  if(layoutManager.findFirstVisibleItemposition()!=0){//如果刷新完毕的时候用户没有注视header//   mheaderVIEw.settopmargin(0);//   return;//  }  if(timer!=null)timer.cancel();  final TimerTask timerTask = new TimerTask() {   @OverrIDe   public voID run() {    if(mheaderVIEw==null){     if(timer!=null)timer.cancel();     return;    }//    Log.i("Alex2","topmargin是"+mheaderVIEw.gettopmargin()+" height是"+mheaderVIEw.getHeight());    if(mheaderVIEw.gettopmargin()<0){     handler.post(new Runnable() {      @OverrIDe      public voID run() {       if (mIsRefreshing) {//如果目前是ready状态或者正在刷新状态        mheaderVIEw.settopmargin(mheaderVIEw.gettopmargin() +2);       }      }     });    } else if(timer!=null){//如果已经完全缩回去了,但是动画还没有结束,就结束掉动画     timer.cancel();    }   }  };  timer = new Timer();  timer.scheduleAtFixedrate(timerTask,16); } /**  * 在用户松手的时候让头部自动收缩回去  */ private voID resetheaderHeight() {  if(mheaderVIEw==null)mheaderVIEw = (CustomDragheaderVIEw) layoutManager.findVIEwByposition(0);  if(layoutManager.findFirstVisibleItemposition()!=0){//如果刷新完毕的时候用户没有注视header   mheaderVIEw.settopmargin(-mheaderVIEw.getRealHeight());   return;  }  if(timer!=null)timer.cancel();  final TimerTask timerTask = new TimerTask() {   @OverrIDe   public voID run() {    if(mheaderVIEw==null)return;//    Log.i("Alex2","topmargin是"+mheaderVIEw.gettopmargin()+" height是"+mheaderVIEw.getHeight());    if(mheaderVIEw.gettopmargin()>-mheaderVIEw.getRealHeight()){//如果header没有完全缩回去     handler.post(new Runnable() {      @OverrIDe      public voID run() {       if (mIsheaderReady || mIsRefreshing) {//如果目前是ready状态或者正在刷新状态//        Log.i("Alex2","现在是ready状态");        int delta = mheaderVIEw.gettopmargin() / 9;        if (delta < 5) delta = 5;        if (mheaderVIEw.gettopmargin() > 0)         mheaderVIEw.settopmargin(mheaderVIEw.gettopmargin() - delta);       } else {//如果是普通状态//        Log.i("Alex2","现在是普通状态");        mheaderVIEw.settopmargin(mheaderVIEw.gettopmargin() - 5);       }      }     });    } else if(timer!=null){//如果已经完全缩回去了,但是动画还没有结束,就结束掉动画     timer.cancel();     handler.post(new Runnable() {      @OverrIDe      public voID run() {       mheaderVIEw.setState(mheaderVIEw.STATE_FINISH);      }     });    }   }  };  timer = new Timer();  timer.scheduleAtFixedrate(timerTask,10); } /**  * 头部是通过ontouchEvent控制的  * @param event  * @return  */ @OverrIDe public boolean ontouchEvent(MotionEvent event) {  switch (event.getAction()) {   case MotionEvent.ACTION_MOVE:    int delta = (int)(event.getY()-oldY);    oldY = event.getY();    if (layoutManager.findVIEwByposition(0) instanceof CustomDragheaderVIEw) {     isheader = true;     updateheaderHeight(delta);//更新margin高度    }else{     isheader = false;     if(mheaderVIEw!=null && !mIsRefreshing)mheaderVIEw.settopmargin(-mheaderVIEw.getRealHeight());    }    break;//   case MotionEvent.ACTION_DOWN://    Log.i("Alex","touch down");//    oldY = event.getY();//    if(timer!=null)timer.cancel();//    break;   case MotionEvent.ACTION_UP://    Log.i("Alex","抬手啦!!!! touch up ");    if(mIsheaderReady && !mIsRefreshing)startRefresh();    if(isheader)resetheaderHeight();//抬手之后恢复高度    break;   case MotionEvent.ACTION_CANCEL://    Log.i("Alex","touch cancel");    break;  }  return super.ontouchEvent(event); } /**  * 因为设置了子元素的onclickListener之后,ontouch方法的down失效,所以要在分发前获取手指的位置  * @param ev  * @return  */ @OverrIDe public boolean dispatchtouchEvent(MotionEvent ev) {  // Todo auto-generated method stub  switch (ev.getAction()) {   case MotionEvent.ACTION_DOWN://    Log.i("Alex","touch down分发前");    oldY = ev.getY();    if (timer != null) timer.cancel();    break;  }  return super.dispatchtouchEvent(ev); } public voID setonRefreshListener(OnRefreshListener Listener){  this.refreshListener = Listener; } /**  * 设置是否支持下啦刷新的功能  *  * @param enable  */ public voID setPullRefreshEnable(boolean enable) {  mIsRefreshing = false;  mEnablePullRefresh = enable;  if(mheaderVIEw==null)return;  if (!mEnablePullRefresh) {   mheaderVIEw.setonClickListener(null);  } else {   mheaderVIEw.setState(CustomDragFooterVIEw.STATE_norMAL);   mheaderVIEw.setVisibility(VISIBLE);  } } /**  * 停止下拉刷新,并且通过动画让头部自己缩回去  */ public voID stopRefresh() {  if (mIsRefreshing == true) {   mIsRefreshing = false;   mIsheaderReady = false;   if(mheaderVIEw==null)return;   mheaderVIEw.setState(CustomDragFooterVIEw.STATE_norMAL);   resetheaderHeight();  } } /**  * 在用户没有用手控制的情况下,通过动画把头部露出来并且执行刷新  */ public voID forceRefresh(){  if(mheaderVIEw==null)mheaderVIEw = (CustomDragheaderVIEw) layoutManager.findVIEwByposition(0);  if(mheaderVIEw!=null)mheaderVIEw.setState(CustomDragheaderVIEw.STATE_REFRESHING);  mIsRefreshing = true;  Log.i("Alex2","现在开始强制刷新");  mIsheaderReady = false;  smoothShowheader();  if (refreshListener != null)refreshListener.onRefresh(); } private voID startRefresh() {  mIsRefreshing = true;  mheaderVIEw.setState(CustomDragheaderVIEw.STATE_REFRESHING);  Log.i("Alex2","现在开始加载");  mIsheaderReady = false;  if (refreshListener != null) refreshListener.onRefresh(); } public interface OnRefreshListener{  public voID onRefresh(); } /**  * 适用于本recycler的头部下拉刷新vIEw  */ public static class CustomDragheaderVIEw extends linearLayout {  public final static int STATE_norMAL = 0;  public final static int STATE_READY = 1;  public final static int STATE_REFRESHING = 2;  public final static int STATE_FINISH = 3;  public float screenDensity;  private final int ROTATE_ANIM_DURATION = 180;  private Context mContext;  private VIEw mContentVIEw;  private VIEw mProgressbar;  private ImageVIEw mArrowImageVIEw;  private TextVIEw mHintTextVIEw;  private Animation mRotateUpAnim;  private Animation mRotateDownAnim;  public CustomDragheaderVIEw(Context context) {   super(context);   initVIEw(context);  }  public CustomDragheaderVIEw(Context context,AttributeSet attrs) {   super(context,attrs);   initVIEw(context);  }  private int mState;  public voID setState(int state) {   if (state == mState)    return;   if (state == STATE_REFRESHING) { // 显示进度    mArrowImageVIEw.clearanimation();    mArrowImageVIEw.setVisibility(VIEw.INVISIBLE);    mProgressbar.setVisibility(VIEw.VISIBLE);   } else { // 显示箭头图片    mArrowImageVIEw.setVisibility(VIEw.VISIBLE);    mProgressbar.setVisibility(VIEw.INVISIBLE);   }   switch (state) {    case STATE_norMAL:     if (mState == STATE_READY) {      mArrowImageVIEw.startAnimation(mRotateDownAnim);      mHintTextVIEw.setText(R.string.xListvIEw_header_hint_normal);     }     else if (mState == STATE_REFRESHING) {//如果是从刷新状态过来//      mArrowImageVIEw.clearanimation();      mArrowImageVIEw.setVisibility(INVISIBLE);      mHintTextVIEw.setText("load completed");     }     break;    case STATE_READY:     if (mState != STATE_READY) {      mArrowImageVIEw.clearanimation();      mArrowImageVIEw.startAnimation(mRotateUpAnim);     }      mHintTextVIEw.setText(R.string.xListvIEw_header_hint_ready);     break;    case STATE_REFRESHING:      mHintTextVIEw.setText(R.string.xListvIEw_header_hint_loading);     break;    case STATE_FINISH:     mArrowImageVIEw.setVisibility(VIEw.VISIBLE);     mHintTextVIEw.setText(R.string.xListvIEw_header_hint_normal);     break;    default:   }   mState = state;  }  public voID settopmargin(int height) {   if (mContentVIEw==null) return ;   LayoutParams lp = (LayoutParams)mContentVIEw.getLayoutParams();   lp.topmargin = height;   mContentVIEw.setLayoutParams(lp);  }  //  public int gettopmargin() {   LayoutParams lp = (LayoutParams)mContentVIEw.getLayoutParams();   return lp.topmargin;  }  public voID setHeight(int height){   if (mContentVIEw==null) return ;   LayoutParams lp = (LayoutParams)mContentVIEw.getLayoutParams();   lp.height = height;   mContentVIEw.setLayoutParams(lp);  }  private int realHeight;  /**   * 得到这个headerVIEw真实的高度,而且这个高度是自己定的   * @return   */  public int getRealHeight(){   return realHeight;  }  private voID initVIEw(Context context) {   mContext = context;   this.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT));//recyclerVIEw里不加这句话的话宽度就会比较窄   linearLayout moreVIEw = (linearLayout) LayoutInflater.from(mContext).inflate(R.layout.xListvIEw_header,null);   addVIEw(moreVIEw);   moreVIEw.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT));   mContentVIEw = moreVIEw.findVIEwByID(R.ID.xListvIEw_header_content);   LayoutParams lp = (LayoutParams)mContentVIEw.getLayoutParams();   Log.i("Alex","初始height是" + mContentVIEw.getHeight());   lp.height = 150;//手动设置高度,如果要手动加载更多的时候才设置   screenDensity = getContext().getResources().getdisplayMetrics().density;//设置屏幕密度,用来px向dp转化   lp.height = dp2px(screenDensity,header_HEIGHT);//头部高度75dp   realHeight = lp.height;   lp.topmargin = -lp.height;   mContentVIEw.setLayoutParams(lp);   mArrowImageVIEw = (ImageVIEw) findVIEwByID(R.ID.xListvIEw_header_arrow);   mHintTextVIEw = (TextVIEw) findVIEwByID(R.ID.xListvIEw_header_hint_textvIEw);   mHintTextVIEw.setpadding(0,dp2px(screenDensity,3),0);//不知道为什么这个文字总会向上偏一下,所以要补回来   mProgressbar = findVIEwByID(R.ID.xListvIEw_header_progressbar);   mRotateUpAnim = new RotateAnimation(0.0f,-180.0f,Animation.relative_TO_SELF,0.5f,0.5f);   mRotateUpAnim.setDuration(ROTATE_ANIM_DURATION);   mRotateUpAnim.setFillAfter(true);   mRotateDownAnim = new RotateAnimation(-180.0f,0.0f,0.5f);   mRotateDownAnim.setDuration(ROTATE_ANIM_DURATION);   mRotateDownAnim.setFillAfter(true);  } } public static int dp2px(float density,int dp) {  if (dp == 0) {   return 0;  }  return (int) (dp * density + 0.5f); } public static class CustomDragRecyclerFooterVIEw extends linearLayout {  public final static int STATE_norMAL = 0;  public final static int STATE_READY = 1;  public final static int STATE_LOADING = 2;  public final static int STATE_ERROR = 3;  private Context mContext;  private VIEw mContentVIEw;  private VIEw mProgressbar;  private TextVIEw mHintVIEw;  public CustomDragRecyclerFooterVIEw(Context context) {   super(context);   initVIEw(context);  }  public CustomDragRecyclerFooterVIEw(Context context,attrs);   initVIEw(context);  }  public voID setState(int state) {   mProgressbar.setVisibility(VIEw.INVISIBLE);//   mHintVIEw.setVisibility(VIEw.INVISIBLE);   if (state == STATE_READY) {    mHintVIEw.setVisibility(VIEw.VISIBLE);    mHintVIEw.setText("松手加载更多");   } else if (state == STATE_LOADING) {    mProgressbar.setVisibility(VIEw.VISIBLE);    mHintVIEw.setVisibility(INVISIBLE);   } else if(state == STATE_ERROR){    mProgressbar.setVisibility(GONE);    mHintVIEw.setVisibility(VISIBLE);    mHintVIEw.setText(R.string.xListvIEw_footer_hint_ready);   }   else {    mHintVIEw.setVisibility(VIEw.VISIBLE);    mHintVIEw.setText(R.string.xListvIEw_footer_hint_normal);    mHintVIEw.setText("Load more");   }  }  public voID setBottommargin(int height) {   if (height < 0) return ;   LayoutParams lp = (LayoutParams)mContentVIEw.getLayoutParams();   lp.bottommargin = height;   mContentVIEw.setLayoutParams(lp);  }  public int getBottommargin() {   LayoutParams lp = (LayoutParams)mContentVIEw.getLayoutParams();   return lp.bottommargin;  }  /**   * normal status   */  public voID normal() {   mHintVIEw.setVisibility(VIEw.VISIBLE);   mProgressbar.setVisibility(VIEw.GONE);  }  /**   * loading status   */  public voID loading() {   mHintVIEw.setVisibility(VIEw.GONE);   mProgressbar.setVisibility(VIEw.VISIBLE);  }  /**   * hIDe footer when disable pull load more   */  public voID hIDe() {   LayoutParams lp = (LayoutParams)mContentVIEw.getLayoutParams();   lp.height = 1;//这里如果设为0那么layoutmanger就会抓不到   mContentVIEw.setLayoutParams(lp);   mContentVIEw.setBackgroundcolor(color.BLACK);//这里的颜色要和自己的背景色一致  }  /**   * show footer   */  public voID show() {   LayoutParams lp = (LayoutParams)mContentVIEw.getLayoutParams();   lp.height = LayoutParams.WRAP_CONTENT;   lp.wIDth = LayoutParams.MATCH_PARENT;   mContentVIEw.setLayoutParams(lp);   mContentVIEw.setBackgroundcolor(color.WHITE);//这里的颜色要和自己的背景色一致  }  private voID initVIEw(Context context) {   mContext = context;   this.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT));   linearLayout moreVIEw = (linearLayout) LayoutInflater.from(mContext).inflate(R.layout.layout_customdragfootervIEw,LayoutParams.WRAP_CONTENT));   mContentVIEw = moreVIEw.findVIEwByID(R.ID.rlContentVIEw);   mProgressbar = moreVIEw.findVIEwByID(R.ID.pbContentVIEw);   mHintVIEw = (TextVIEw)moreVIEw.findVIEwByID(R.ID.ctvContentVIEw);   mHintVIEw.setText("load more");//   mProgressbar.setVisibility(VISIBLE);//一直会显示转圈,自动加载更多时使用  } } /**  * 为了防止代码上的混乱,使用这个recyclerVIEw自己内置的一个adapter  * @param <T>  */ public static abstract class AlxDragRecyclerVIEwAdapter<T> extends RecyclerVIEw.Adapter<RecyclerVIEw.VIEwHolder>{  protected static final int TYPE_header = 436874;  protected static final int TYPE_ITEM = 256478;  protected static final int TYPE_FOOTER = 9621147;  private int ITEM;  private VIEwHolder vhItem;  protected boolean loadMore;  private List<T> dataList;  public List<T> getDataList() {   return dataList;  }  public voID setDataList(List<T> dataList) {   this.dataList = dataList;  }  public AlxDragRecyclerVIEwAdapter(List<T> dataList,int itemLayout,boolean pullEnable){   this.dataList = dataList;   this.ITEM = itemLayout;   this.loadMore = pullEnable;  }  public abstract VIEwHolder setItemVIEwHolder(VIEw itemVIEw);  private T getobject(int position){   if(dataList!=null && dataList.size()>=position)return dataList.get(position-1);//如果有header   return null;  }  @OverrIDe  public RecyclerVIEw.VIEwHolder onCreateVIEwHolder(VIEwGroup parent,int vIEwType) {   if (vIEwType == TYPE_ITEM) {    //inflate your layout and pass it to vIEw holder    VIEw itemVIEw = LayoutInflater.from(parent.getContext()).inflate(ITEM,null);    Log.i("Alex","itemVIEw是"+itemVIEw);    this.vhItem = setItemVIEwHolder(itemVIEw);    Log.i("Alex","vhItem是"+vhItem);    return vhItem;   } else if (vIEwType == TYPE_header) {    //inflate your layout and pass it to vIEw holder    VIEw headerVIEw = new CustomDragheaderVIEw(parent.getContext());    return new VHheader(headerVIEw);   } else if(vIEwType==TYPE_FOOTER){    CustomDragRecyclerFooterVIEw footerVIEw = new CustomDragRecyclerFooterVIEw(parent.getContext());    return new VHFooter(footerVIEw);   }   throw new RuntimeException("there is no type that matches the type " + vIEwType + " + make sure your using types correctly");  }  public voID setPullLoadMoreEnable(boolean enable){   this.loadMore = enable;  }  public boolean getPullLoadMoreEnable(){return loadMore;}  @OverrIDe  public voID onBindVIEwHolder(RecyclerVIEw.VIEwHolder holder,int position) {//相当于getVIEw   Log.i("Alex","正在绑定"+position+" "+holder.getClass());   if (vhItem!=null && holder.getClass() == vhItem.getClass()) {    //cast holder to VHItem and set data    initItemVIEw(holder,position,getobject(position));   }else if (holder instanceof AlxDragRecyclerVIEwAdapter.VHheader) {    //cast holder to VHheader and set data for header.   }else if(holder instanceof AlxDragRecyclerVIEwAdapter.VHFooter){    if(!loadMore)((VHFooter)holder).footerVIEw.hIDe();//第一次初始化显示的时候要不要显示footerVIEw   }  }  @OverrIDe  public int getItemCount() {   return (dataList==null ||dataList.size()==0)?1:dataList.size() + 2;//如果有header,若List不存在或大小为0就没有footVIEw,反之则有  }//这里要考虑到头尾部,多以要加2  /**   * 根据位置判断这里该用哪个VIEwHolder   * @param position   * @return   */  @OverrIDe  public int getItemVIEwType(int position) {   if (position == 0)return TYPE_header;   else if(isPositonFooter(position))return TYPE_FOOTER;   return TYPE_ITEM;  }  protected boolean isPositonFooter(int position){//这里的position从0算起    if (dataList == null && position == 1) return true;//如果没有item    return position == dataList.size() + 1;//如果有item(也许为0)  }//  class VHItem extends RecyclerVIEw.VIEwHolder {//   public VHItem(VIEw itemVIEw) {//    super(itemVIEw);//   }//   public VIEw getItemVIEw(){return itemVIEw;}//  }//  protected class VHheader extends RecyclerVIEw.VIEwHolder {   public VHheader(VIEw headerVIEw) {    super(headerVIEw);   }  }  protected class VHFooter extends RecyclerVIEw.VIEwHolder {   public CustomDragRecyclerFooterVIEw footerVIEw;   public VHFooter(VIEw itemVIEw) {    super(itemVIEw);    footerVIEw = (CustomDragRecyclerFooterVIEw)itemVIEw;   }  }  public abstract voID initItemVIEw(VIEwHolder itemHolder,int posion,T entity); }}


总结

以上是内存溢出为你收集整理的Android仿XListView支持下拉刷新和上划加载更多的自定义RecyclerView全部内容,希望文章能够帮你解决Android仿XListView支持下拉刷新和上划加载更多的自定义RecyclerView所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1141748.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存