《android》下拉刷新上拉加载更多控件 PullToRefreshView

 

前段时间项目用到了下拉刷新,用到了PullToRefreshView,于是我拿出一点自己做了一个demo,分享一下。

PullToRefreshView是一个上拉刷新下拉加载的一个自定义组件,它支持三种view,ListView,GridView和ScrollView的刷新操作

效果图

下面上PullToRefreshView的代码

 

public class PullToRefreshView extends LinearLayout {
 // refresh states
 private static final int  PULL_TO_REFRESH  = 2;
 private static final int  RELEASE_TO_REFRESH = 3;
 private static final int  REFRESHING   = 4;
 // pull state
 private static final int  PULL_UP_STATE  = 0;
 private static final int  PULL_DOWN_STATE  = 1;
 /**
  * last x
  */
 private int      mLastMotionX;
 /**
  * last y
  */
 private int      mLastMotionY;
 /**
  * lock
  */
 private boolean     mLock;
 /**
  * header view
  */
 private View     mHeaderView;
 /**
  * footer view
  */
 private View     mFooterView;
 /**
  * list or grid
  */
 private AdapterView<?>   mAdapterView;
 /**
  * scrollview
  */
 private ScrollView    mScrollView;
 /**
  * header view height
  */
 private int      mHeaderViewHeight;
 /**
  * footer view height
  */
 private int      mFooterViewHeight;
 /**
  * header view image
  */
 private ImageView    mHeaderImageView;
 /**
  * footer view image
  */
 private ImageView    mFooterImageView;
 /**
  * header tip text
  */
 private TextView    mHeaderTextView;
 /**
  * footer tip text
  */
 private TextView    mFooterTextView;
 /**
  * header refresh time
  */
 private TextView    mHeaderUpdateTextView;
 /**
  * footer refresh time
  */
 private TextView    mFooterUpdateTextView;
 /**
  * header progress bar
  */
 private ProgressBar    mHeaderProgressBar;
 /**
  * footer progress bar
  */
 private ProgressBar    mFooterProgressBar;
 /**
  * layout inflater
  */
 private LayoutInflater   mInflater;
 /**
  * header view current state
  */
 private int      mHeaderState;
 /**
  * footer view current state
  */
 private int      mFooterState;
 /**
  * pull state,pull up or pull down;PULL_UP_STATE or PULL_DOWN_STATE
  */
 private int      mPullState;
 /**
  * 变为向下的箭头,改变箭头方向
  */
 private RotateAnimation   mFlipAnimation;
 /**
  * 变为逆向的箭头,旋转
  */
 private RotateAnimation   mReverseFlipAnimation;
 /**
  * footer refresh listener
  */
 private OnFooterRefreshListener mOnFooterRefreshListener;
 /**
  * footer refresh listener
  */
 private OnHeaderRefreshListener mOnHeaderRefreshListener;
 /**
  * last update time
  */
 private String     mLastUpdateTime;
 /**
  * diabled pull up refresh
  */
 private boolean     mDisablePullUpRefresh;
 /**
  * diabled pull down refresh
  */
 private boolean     mDisablePullDownRefresh;

 public PullToRefreshView(Context context, AttributeSet attrs) {
  super(context, attrs);
  init();
 }

 public PullToRefreshView(Context context) {
  super(context);
  init();
 }

 /**
  * 启用下拉刷新功能
  */
 public void enablePullUpRefresh() {
  mDisablePullUpRefresh = false;
  mFooterView.setVisibility(View.VISIBLE);
 }

 /**
  * 禁用下拉刷新功能
  */
 public void disablePullUpRefresh() {
  mDisablePullUpRefresh = true;
  mFooterView.setVisibility(View.GONE);
 }

 /**
  * 启用上拉刷新功能
  */
 public void enablePullDownRefresh() {
  mDisablePullDownRefresh = false;
 }

 /**
  * 禁用上拉刷新功能
  */
 public void disablePullDownRefresh() {
  mDisablePullDownRefresh = true;
 }

 /**
  * init
  *
  * @description
  * @param context
  *            hylin 2012-7-26上午10:08:33
  */
 private void init() {
  // Load all of the animations we need in code rather than through XML
  mFlipAnimation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
  mFlipAnimation.setInterpolator(new LinearInterpolator());
  mFlipAnimation.setDuration(250);
  mFlipAnimation.setFillAfter(true);
  mReverseFlipAnimation = new RotateAnimation(-180, 0, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
  mReverseFlipAnimation.setInterpolator(new LinearInterpolator());
  mReverseFlipAnimation.setDuration(250);
  mReverseFlipAnimation.setFillAfter(true);

  mInflater = LayoutInflater.from(getContext());
  // header view 在此添加,保证是第一个添加到linearlayout的最上端
  addHeaderView();
 }

 private void addHeaderView() {
  // header view
  mHeaderView = mInflater.inflate(R.layout.refresh_header, this, false);

  mHeaderImageView = (ImageView) mHeaderView.findViewById(R.id.pull_to_refresh_image);
  mHeaderTextView = (TextView) mHeaderView.findViewById(R.id.pull_to_refresh_text);
  mHeaderUpdateTextView = (TextView) mHeaderView.findViewById(R.id.pull_to_refresh_updated_at);
  mHeaderProgressBar = (ProgressBar) mHeaderView.findViewById(R.id.pull_to_refresh_progress);
  // header layout
  measureView(mHeaderView);
  mHeaderViewHeight = mHeaderView.getMeasuredHeight();
  LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, mHeaderViewHeight);
  // 设置topMargin的值为负的header View高度,即将其隐藏在最上方
  params.topMargin = -(mHeaderViewHeight);
  // mHeaderView.setLayoutParams(params1);
  addView(mHeaderView, params);

 }

 private void addFooterView() {
  // footer view
  mFooterView = mInflater.inflate(R.layout.refresh_footer, this, false);
  mFooterImageView = (ImageView) mFooterView.findViewById(R.id.pull_to_load_image);
  mFooterTextView = (TextView) mFooterView.findViewById(R.id.pull_to_load_text);
  mFooterUpdateTextView = (TextView) mFooterView.findViewById(R.id.pull_to_load_updated_at);
  mFooterProgressBar = (ProgressBar) mFooterView.findViewById(R.id.pull_to_load_progress);
  // footer layout
  measureView(mFooterView);
  mFooterViewHeight = mFooterView.getMeasuredHeight();
  LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, mFooterViewHeight);
  // int top = getHeight();
  // params.topMargin
  // =getHeight();//在这里getHeight()==0,但在onInterceptTouchEvent()方法里getHeight()已经有值了,不再是0;
  // getHeight()什么时候会赋值,稍候再研究一下
  // 由于是线性布局可以直接添加,只要AdapterView的高度是MATCH_PARENT,那么footer view就会被添加到最后,并隐藏
  addView(mFooterView, params);
 }

 @Override
 protected void onFinishInflate() {
  super.onFinishInflate();
  // footer view 在此添加保证添加到linearlayout中的最后
  addFooterView();
  initContentAdapterView();
 }

 /**
  * init AdapterView like ListView,GridView and so on;or init ScrollView
  *
  * @description hylin 2012-7-30下午8:48:12
  */
 private void initContentAdapterView() {
  int count = getChildCount();
  if (count < 3) {
   throw new IllegalArgumentException("this layout must contain 3 child views,and AdapterView or ScrollView must in the second position!");
  }
  View view = null;
  for (int i = 0; i < count - 1; ++i) {
   view = getChildAt(i);
   if (view instanceof AdapterView<?>) {
    mAdapterView = (AdapterView<?>) view;
   }
   if (view instanceof ScrollView) {
    // finish later
    mScrollView = (ScrollView) view;
   }
  }
  if (mAdapterView == null && mScrollView == null) {
   throw new IllegalArgumentException("must contain a AdapterView or ScrollView in this layout!");
  }
 }

 private void measureView(View child) {
  ViewGroup.LayoutParams p = child.getLayoutParams();
  if (p == null) {
   p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
  }

  int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);
  int lpHeight = p.height;
  int childHeightSpec;
  if (lpHeight > 0) {
   childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
  }
  else {
   childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
  }
  child.measure(childWidthSpec, childHeightSpec);
 }

 @Override
 public boolean onInterceptTouchEvent(MotionEvent e) {
  int y = (int) e.getRawY();
  int x = (int) e.getRawX();
  switch (e.getAction()) {
  case MotionEvent.ACTION_DOWN:
   // 首先拦截down事件,记录y坐标
   mLastMotionY = y;
   mLastMotionX = x;
   break;
  case MotionEvent.ACTION_MOVE:
   // deltaY > 0 是向下运动,< 0是向上运动
   int deltaY = y - mLastMotionY;
   int deletaX = x - mLastMotionX;
   if (Math.abs(deletaX) >= Math.abs(deltaY)) {
    return false;
   }
   if (isRefreshViewScroll(deltaY)) {
    return true;
   }
   break;
  case MotionEvent.ACTION_UP:
  case MotionEvent.ACTION_CANCEL:
   break;
  }
  return false;
 }

 /*
  * 如果在onInterceptTouchEvent()方法中没有拦截(即onInterceptTouchEvent()方法中 return
  * false)则由PullToRefreshView 的子View来处理;否则由下面的方法来处理(即由PullToRefreshView自己来处理)
  */
 @Override
 public boolean onTouchEvent(MotionEvent event) {
  if (mLock) {
   return true;
  }
  int y = (int) event.getRawY();
  int x = (int) event.getRawX();
  switch (event.getAction()) {
  case MotionEvent.ACTION_DOWN:
   // onInterceptTouchEvent已经记录
   // mLastMotionY = y;
   break;
  case MotionEvent.ACTION_MOVE:
   int deltaY = y - mLastMotionY;
   int deltaX = x - mLastMotionX;
   if (mPullState == PULL_DOWN_STATE && !mDisablePullDownRefresh) {
    // PullToRefreshView执行下拉
    headerPrepareToRefresh(deltaY);
    // setHeaderPadding(-mHeaderViewHeight);
   }
   else if (mPullState == PULL_UP_STATE && !mDisablePullUpRefresh) {
    // PullToRefreshView执行上拉
    footerPrepareToRefresh(deltaY);
   }
   mLastMotionY = y;
   mLastMotionX = x;
   break;
  case MotionEvent.ACTION_UP:
  case MotionEvent.ACTION_CANCEL:
   int topMargin = getHeaderTopMargin();
   if (mPullState == PULL_DOWN_STATE) {
    if (topMargin >= 0) {
     // 开始刷新
     headerRefreshing();
    }
    else {
     // 还没有执行刷新,重新隐藏
     if (!mDisablePullDownRefresh) {
      setHeaderTopMargin(-mHeaderViewHeight);
     }
    }
   }
   else if (mPullState == PULL_UP_STATE) {
    if (Math.abs(topMargin) >= mHeaderViewHeight + mFooterViewHeight) {
     // 开始执行footer 刷新
     footerRefreshing();
    }
    else {
     // 还没有执行刷新,重新隐藏
     if (!mDisablePullUpRefresh) {
      setHeaderTopMargin(-mHeaderViewHeight);
     }
    }
   }
   break;
  }
  return super.onTouchEvent(event);
 }

 /**
  * 是否应该到了父View,即PullToRefreshView滑动
  *
  * @param deltaY
  *            , deltaY > 0 是向下运动,< 0是向上运动
  * @return
  */
 private boolean isRefreshViewScroll(int deltaY) {
  if (mHeaderState == REFRESHING || mFooterState == REFRESHING) {
   return false;
  }
  //对于ListView和GridView
  if (mAdapterView != null) {
   // 子view(ListView or GridView)滑动到最顶端
   if (deltaY > 0) {

    View child = mAdapterView.getChildAt(0);
    if (child == null) {
     // 如果mAdapterView中没有数据,不拦截
     return false;
    }
    if (mAdapterView.getFirstVisiblePosition() == 0 && child.getTop() == 0) {
     mPullState = PULL_DOWN_STATE;
     return true;
    }
    int top = child.getTop();
    int padding = mAdapterView.getPaddingTop();
    if (mAdapterView.getFirstVisiblePosition() == 0 && Math.abs(top - padding) <= 8) {//这里之前用3可以判断,但现在不行,还没找到原因
     mPullState = PULL_DOWN_STATE;
     return true;
    }

   }
   else if (deltaY < 0) {
    View lastChild = mAdapterView.getChildAt(mAdapterView.getChildCount() - 1);
    if (lastChild == null) {
     // 如果mAdapterView中没有数据,不拦截
     return false;
    }
    // 最后一个子view的Bottom小于父View的高度说明mAdapterView的数据没有填满父view,
    // 等于父View的高度说明mAdapterView已经滑动到最后
    if (lastChild.getBottom() <= getHeight() && mAdapterView.getLastVisiblePosition() == mAdapterView.getCount() - 1) {
     mPullState = PULL_UP_STATE;
     return true;
    }
   }
  }
  // 对于ScrollView
  if (mScrollView != null) {
   // 子scroll view滑动到最顶端
   View child = mScrollView.getChildAt(0);
   if (deltaY > 0 && mScrollView.getScrollY() == 0) {
    mPullState = PULL_DOWN_STATE;
    return true;
   }
   else if (deltaY < 0 && child.getMeasuredHeight() <= getHeight() + mScrollView.getScrollY()) {
    mPullState = PULL_UP_STATE;
    return true;
   }
  }
  return false;
 }

 /**
  * header 准备刷新,手指移动过程,还没有释放
  *
  * @param deltaY
  *            ,手指滑动的距离
  */
 private void headerPrepareToRefresh(int deltaY) {
  int newTopMargin = changingHeaderViewTopMargin(deltaY);
  // 当header view的topMargin>=0时,说明已经完全显示出来了,修改header view 的提示状态
  if (newTopMargin >= 0 && mHeaderState != RELEASE_TO_REFRESH) {
   mHeaderTextView.setText("松开后刷新");
   mHeaderUpdateTextView.setVisibility(View.VISIBLE);
   mHeaderImageView.clearAnimation();
   mHeaderImageView.startAnimation(mFlipAnimation);
   mHeaderState = RELEASE_TO_REFRESH;
  }
  else if (newTopMargin < 0 && newTopMargin > -mHeaderViewHeight) {// 拖动时没有释放
   mHeaderImageView.clearAnimation();
   mHeaderImageView.startAnimation(mFlipAnimation);
   // mHeaderImageView.
   mHeaderTextView.setText("下拉刷新");
   mHeaderState = PULL_TO_REFRESH;
  }
 }

 /**
  * footer 准备刷新,手指移动过程,还没有释放 移动footer view高度同样和移动header view
  * 高度是一样,都是通过修改header view的topmargin的值来达到
  *
  * @param deltaY
  *            ,手指滑动的距离
  */
 private void footerPrepareToRefresh(int deltaY) {
  int newTopMargin = changingHeaderViewTopMargin(deltaY);
  // 如果header view topMargin 的绝对值大于或等于header + footer 的高度
  // 说明footer view 完全显示出来了,修改footer view 的提示状态
  if (Math.abs(newTopMargin) >= (mHeaderViewHeight + mFooterViewHeight) && mFooterState != RELEASE_TO_REFRESH) {
   mFooterTextView.setText("松开后加载");
   mFooterImageView.clearAnimation();
   mFooterImageView.startAnimation(mFlipAnimation);
   mFooterState = RELEASE_TO_REFRESH;
  }
  else if (Math.abs(newTopMargin) < (mHeaderViewHeight + mFooterViewHeight)) {
   mFooterImageView.clearAnimation();
   mFooterImageView.startAnimation(mFlipAnimation);
   mFooterTextView.setText("上拉加载更多");
   mFooterState = PULL_TO_REFRESH;
  }
 }

 /**
  * 修改Header view top margin的值
  *
  * @description
  * @param deltaY
  * @return hylin 2012-7-31下午1:14:31
  */
 private int changingHeaderViewTopMargin(int deltaY) {
  LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams();
  float newTopMargin = params.topMargin + deltaY * 0.3f;
  //这里对上拉做一下限制,因为当前上拉后然后不释放手指直接下拉,会把下拉刷新给触发了,感谢网友yufengzungzhe的指出
  //表示如果是在上拉后一段距离,然后直接下拉
  if (deltaY > 0 && mPullState == PULL_UP_STATE && Math.abs(params.topMargin) <= mHeaderViewHeight) {
   return params.topMargin;
  }
  //同样地,对下拉做一下限制,避免出现跟上拉操作时一样的bug
  if (deltaY < 0 && mPullState == PULL_DOWN_STATE && Math.abs(params.topMargin) >= mHeaderViewHeight) {
   return params.topMargin;
  }
  params.topMargin = (int) newTopMargin;
  mHeaderView.setLayoutParams(params);
  invalidate();
  return params.topMargin;
 }

 /**
  * header refreshing
  *
  * @description hylin 2012-7-31上午9:10:12
  */
 private void headerRefreshing() {
  headerRefreshing(true);
 }

 /**
  * header refreshing
  *
  * @description hylin 2012-7-31上午9:10:12
  */
 private void headerRefreshing(boolean notify) {
  mHeaderState = REFRESHING;
  setHeaderTopMargin(0);
  mHeaderImageView.setVisibility(View.GONE);
  mHeaderImageView.clearAnimation();
  mHeaderImageView.setImageDrawable(null);
  mHeaderProgressBar.setVisibility(View.VISIBLE);
  mHeaderTextView.setText("正在加载");
  if (mOnHeaderRefreshListener != null && notify) {
   mOnHeaderRefreshListener.onHeaderRefresh(this);
  }
 }

 /**
  * footer refreshing
  *
  * @description hylin 2012-7-31上午9:09:59
  */
 private void footerRefreshing() {
  mFooterState = REFRESHING;
  int top = mHeaderViewHeight + mFooterViewHeight;
  setHeaderTopMargin(-top);
  mFooterImageView.setVisibility(View.GONE);
  mFooterImageView.clearAnimation();
  mFooterImageView.setImageDrawable(null);
  mFooterProgressBar.setVisibility(View.VISIBLE);
  mFooterTextView.setText("加载中");
  if (mOnFooterRefreshListener != null) {
   mOnFooterRefreshListener.onFooterRefresh(this);
  }
 }

 /**
  * 设置header view 的topMargin的值
  *
  * @description
  * @param topMargin
  *            ,为0时,说明header view 刚好完全显示出来; 为-mHeaderViewHeight时,说明完全隐藏了
  *            hylin 2012-7-31上午11:24:06
  */
 private void setHeaderTopMargin(int topMargin) {
  LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams();
  params.topMargin = topMargin;
  mHeaderView.setLayoutParams(params);
  invalidate();
 }

 /**
  * header view 完成更新后恢复初始状态
  *
  * @description hylin 2012-7-31上午11:54:23
  */
 public void onHeaderRefreshComplete() {
  setHeaderTopMargin(-mHeaderViewHeight);
  mHeaderImageView.setVisibility(View.VISIBLE);
  mHeaderImageView.setImageResource(R.drawable.ic_pulltorefresh_arrow);
  mHeaderTextView.setText("下拉刷新");
  mHeaderProgressBar.setVisibility(View.GONE);
  // mHeaderUpdateTextView.setText("");
  mHeaderState = PULL_TO_REFRESH;
 }

 /**
  * Resets the list to a normal state after a refresh.
  *
  * @param lastUpdated
  *            Last updated at.
  */
 public void onHeaderRefreshComplete(CharSequence lastUpdated) {
  setLastUpdated(lastUpdated);
  onHeaderRefreshComplete();
 }

 public void onFooterRefreshComplete(CharSequence lastUpdated) {
  setFooterLastUpdated(lastUpdated);
  onFooterRefreshComplete();
 }

 /**
  * footer view 完成更新后恢复初始状态
  */
 public void onFooterRefreshComplete() {
  setHeaderTopMargin(-mHeaderViewHeight);
  mFooterImageView.setVisibility(View.VISIBLE);
  mFooterImageView.setImageResource(R.drawable.ic_pulltorefresh_arrow_up);
  mFooterTextView.setText("上拉加载更多");
  mFooterProgressBar.setVisibility(View.GONE);
  // mHeaderUpdateTextView.setText("");
  mFooterState = PULL_TO_REFRESH;
 }

 /**
  * Set a text to represent when the list was last updated.
  *
  * @param lastUpdated
  *            Last updated at.
  */
 public void setLastUpdated(CharSequence lastUpdated) {
  if (lastUpdated != null) {
   mHeaderUpdateTextView.setVisibility(View.VISIBLE);
   mHeaderUpdateTextView.setText(lastUpdated);
  }
  else {
   mHeaderUpdateTextView.setVisibility(View.GONE);
  }
 }

 /**
  * Set a text to represent when the footer list was last updated.
  *
  * @param lastUpdated
  *            Last updated at.
  */
 public void setFooterLastUpdated(CharSequence lastUpdated) {
  if (lastUpdated != null) {
   mFooterUpdateTextView.setVisibility(View.VISIBLE);
   mFooterUpdateTextView.setText(lastUpdated);
  }
  else {
   mFooterUpdateTextView.setVisibility(View.GONE);
  }
 }

 /**
  * 获取当前header view 的topMargin
  *
  * @description
  * @return hylin 2012-7-31上午11:22:50
  */
 private int getHeaderTopMargin() {
  LayoutParams params = (LayoutParams) mHeaderView.getLayoutParams();
  return params.topMargin;
 }

 /**
  * lock
  *
  * @description hylin 2012-7-27下午6:52:25
  */
 private void lock() {
  mLock = true;
 }

 /**
  * unlock
  *
  * @description hylin 2012-7-27下午6:53:18
  */
 private void unlock() {
  mLock = false;
 }

 /**
  * 显示加载
  */
 public void showRefrshing() {
  mPullState = PULL_DOWN_STATE;
  headerPrepareToRefresh(mHeaderViewHeight + mFooterViewHeight - 10);
  headerRefreshing(false);
 }

 /**
  * set headerRefreshListener
  *
  * @description
  * @param headerRefreshListener
  *            hylin 2012-7-31上午11:43:58
  */
 public void setOnHeaderRefreshListener(OnHeaderRefreshListener headerRefreshListener) {
  mOnHeaderRefreshListener = headerRefreshListener;
 }

 public void setOnFooterRefreshListener(OnFooterRefreshListener footerRefreshListener) {
  mOnFooterRefreshListener = footerRefreshListener;
 }

 /**
  * Interface definition for a callback to be invoked when list/grid footer
  * view should be refreshed.
  */
 public interface OnFooterRefreshListener {
  public void onFooterRefresh(PullToRefreshView view);
 }

 /**
  * Interface definition for a callback to be invoked when list/grid header
  * view should be refreshed.
  */
 public interface OnHeaderRefreshListener {
  public void onHeaderRefresh(PullToRefreshView view);
 }

}

 

刷新的布局:refresh_footer.xml:

 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pull_to_refresh_header"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:focusable="true">

    <ProgressBar
        android:id="@+id/pull_to_load_progress"
        style="?android:attr/progressBarStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_alignParentLeft="true"
        android:layout_marginLeft="30dp"
        android:indeterminate="true"
        android:visibility="gone" />

    <ImageView
        android:id="@+id/pull_to_load_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_marginLeft="30dp"
        android:layout_toRightOf="@+id/pull_to_load_progress"
        android:src="@drawable/ic_pulltorefresh_arrow_up" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:gravity="center"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/pull_to_load_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:text="正在刷新"
            android:textSize="14sp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/pull_to_load_updated_at"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:textSize="12sp"
            />
    </LinearLayout>

</RelativeLayout>

 

 

refresh_header.xml:

 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pull_to_refresh_header"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="center" >

    <ProgressBar
        android:id="@+id/pull_to_refresh_progress"
        style="?android:attr/progressBarStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_marginLeft="30dip"
        android:layout_marginRight="20dip"
        android:indeterminate="true"
        android:visibility="gone" />

    <ImageView
        android:id="@+id/pull_to_refresh_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_gravity="center"
        android:layout_marginLeft="30dip"
        android:layout_marginRight="20dip"
        android:gravity="center"
        android:src="@drawable/ic_pulltorefresh_arrow"
        android:visibility="visible" />

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:gravity="center"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/pull_to_refresh_text"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:gravity="center"
            android:text="下拉刷新"
            android:textColor="@android:color/black"
            android:textSize="12sp" />

        <TextView
            android:id="@+id/pull_to_refresh_updated_at"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:textColor="@android:color/black"
            android:textSize="12sp" />
    </LinearLayout>

</RelativeLayout>

 

 

 

 

 

 

 

好了到了用的的时候了,首选需要XML需要如下设置

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
   >

    <com.example.view.PullToRefreshView
        android:id="@+id/pull_toRefresh"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >

        <ListView
            android:id="@+id/listview"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" />
    </com.example.view.PullToRefreshView>

</LinearLayout>

 

Activity记得需要实现这2个接口

MainActivity  implements OnHeaderRefreshListener, OnFooterRefreshListener 

mpullToRefreshView = (PullToRefreshView) findViewById(R.id.pull_toRefresh);
  //添加监听器
  mpullToRefreshView.setOnHeaderRefreshListener(this);
  mpullToRefreshView.setOnFooterRefreshListener(this);

 

实现接口会有如下2个方法:

 

 

/**
  * 下拉加载更多调用这个方法!!!
  */
 public void onFooterRefresh(PullToRefreshView view) {

  mpullToRefreshView.postDelayed(new Runnable() {
   public void run() {
      if (mAdapter.getCount() == 30) {//你要判断 服务器下发给你的数据一共有多少条,我这里假如服务器一共有30数据,如果我也加载了30条了,就不要加载更多了!!
      Toast.makeText(MainActivity.this, "没有更多数据", Toast.LENGTH_LONG).show();
      mpullToRefreshView.onFooterRefreshComplete();//调用这个方法 是恢复初始状态
     }
     else {
      //加载更多操作
      mHandler.sendEmptyMessage(GET_MORE);
     }
    }
   }
  }, 1000

 

/**
  * 下拉刷新会调用这个方法
  */
 public void onHeaderRefresh(PullToRefreshView view) {

  mpullToRefreshView.postDelayed(new Runnable() {

   @Override
   public void run() {
           mHandler.sendEmptyMessage(START_REFRESH);
   }
  }, 1000);

 

我这里用handler发送消息去操作,接下拉在handler里面做相应的操作就行了啦,值得注意的是:

 // 这是 4个常用方法,禁用启用的,我在旁边注释了,你到时候根据需求自己加在什么地方就可以了
  //  mpullToRefreshView.disablePullDownRefresh();//禁用上拉刷新
  //  mpullToRefreshView.enablePullDownRefresh();//启用上拉刷新

  //  mpullToRefreshView.disablePullUpRefresh();//禁用下拉加载更多
  //  mpullToRefreshView.enablePullUpRefresh();//启动下拉加载更多

 

 

 

 }

 

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值