自定义ListView上拉刷新,下拉加载更多(一)

来源:互联网 发布:sybase数据库备份 编辑:程序博客网 时间:2024/05/24 01:42

最近写代码,一直都用的别人开源框架实现 上拉刷新,下拉加载更多. 经常出现bug.   所以今天写这篇博客 自己动手做一个自定义ListView实现上拉刷新,下拉加载更多.


下面先看效果图:



由于是演示数据都用的是虚拟数据,

1.首先我们先创建一个自定义View 继承原生的ListView,并初始化它的需要的头布局和脚布局,代码如下:

头布局:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="horizontal">    <FrameLayout        android:layout_margin="5dp"        android:layout_width="50dp"        android:layout_height="50dp" >        <ImageView            android:id="@+id/iv_arrow"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="center"            android:src="@drawable/common_listview_headview_red_arrow" />        <ProgressBar            android:id="@+id/pb"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:indeterminateDrawable="@drawable/shape_progress"            android:visibility="invisible" />    </FrameLayout>    <LinearLayout        android:layout_margin="5dp"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:gravity="center_horizontal"        android:orientation="vertical" >        <TextView            android:id="@+id/tv_title"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_marginTop="5dp"            android:text="下拉刷新"            android:textColor="#F00"            android:textSize="18sp" />        <TextView            android:id="@+id/tv_desc_last_refresh"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_marginTop="5dp"            android:singleLine="true"            android:text="最后刷新时间: 2015-10-11 09:20:35"            android:textColor="#666"            android:textSize="14sp" />    </LinearLayout></LinearLayout>


脚布局:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:gravity="center"    android:orientation="horizontal" >    <ProgressBar        android:layout_margin="5dp"        android:layout_width="50dp"        android:layout_height="50dp"        android:indeterminateDrawable="@drawable/shape_progress" />    <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="加载更多..."        android:textColor="#F00"        android:layout_marginLeft="15dp"        android:textSize="18sp" /></LinearLayout>

2.在自定义listview中对头和脚进行初始化并监听滑动和触摸事件,并初始化它的需要的头布局和脚布局,代码如下:

1.1初始化头布局  

private void initHeaderView() {    mHeaderView = View.inflate(getContext(), R.layout.layout_header_list, null);    mArrowView = mHeaderView.findViewById(R.id.iv_arrow);    pb = (ProgressBar) mHeaderView.findViewById(R.id.pb);    mTitleText = (TextView) mHeaderView.findViewById(R.id.tv_title);    mLastRefreshTime = (TextView) mHeaderView.findViewById(R.id.tv_desc_last_refresh);    // 提前手动测量宽高    mHeaderView.measure(0, 0);// 按照设置的规则测量    mHeaderViewHeight = mHeaderView.getMeasuredHeight();    // 设置内边距, 可以隐藏当前控件 , -自身高度    mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0);    // 在设置数据适配器之前执行添加 头布局/脚布局 的方法.    addHeaderView(mHeaderView);}
1.2初始化脚布局
private void initHeaderView() {    mHeaderView = View.inflate(getContext(), R.layout.layout_header_list, null);    mArrowView = mHeaderView.findViewById(R.id.iv_arrow);    pb = (ProgressBar) mHeaderView.findViewById(R.id.pb);    mTitleText = (TextView) mHeaderView.findViewById(R.id.tv_title);    mLastRefreshTime = (TextView) mHeaderView.findViewById(R.id.tv_desc_last_refresh);    // 提前手动测量宽高    mHeaderView.measure(0, 0);// 按照设置的规则测量    mHeaderViewHeight = mHeaderView.getMeasuredHeight();    // 设置内边距, 可以隐藏当前控件 , -自身高度    mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0);    // 在设置数据适配器之前执行添加 头布局/脚布局 的方法.    addHeaderView(mHeaderView);}

1.3监听listview滑动和触摸事件
 @Override    public boolean onTouchEvent(MotionEvent ev) {        switch (ev.getAction()){            case MotionEvent.ACTION_DOWN: //按下                downY = ev.getY();                break;            case MotionEvent.ACTION_MOVE: //移动                moveY = ev.getY();                // 如果是正在刷新中, 就执行父类的处理                if(currentState == REFRESHING){                    return super.onTouchEvent(ev);                }                float offset = moveY - downY; // 移动的偏移量                if(offset>0&&getFirstVisiblePosition()==0){                 //   int paddingTop = -自身高度 + 偏移量                    int paddingTop = (int) (- mHeaderViewHeight + offset);                    mHeaderView.setPadding(0, paddingTop, 0, 0);                    if(paddingTop>0&&currentState!=RELEASE_REFRESH){                        // 切换成释放刷新模式                        currentState = RELEASE_REFRESH;                        updateHeader(); // 根据最新的状态值更新头布局内容                    }else if(paddingTop<0&&currentState!=PULL_TO_REFRESH){                        // 切换成下拉刷新模式                        currentState = PULL_TO_REFRESH;                        updateHeader(); // 根据最新的状态值更新头布局内容                    }                    return true; // 当前事件被我们处理并消费                }                break;            case  MotionEvent.ACTION_UP:  // 抬起                // 根据刚刚设置状态                if(currentState == PULL_TO_REFRESH) {//       - paddingTop < 0 不完全显示, 恢复                    mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0);                }else if(currentState == RELEASE_REFRESH){//       - paddingTop >= 0 完全显示, 执行正在刷新...                    mHeaderView.setPadding(0, 0, 0, 0);                    currentState = REFRESHING;                    updateHeader();                }                break;            default:                break;        }     return super.onTouchEvent(ev);    }    private void updateHeader() {        switch (currentState){            case PULL_TO_REFRESH:                // 做动画, 改标题                mArrowView.startAnimation(rotateDownAnim);                mTitleText.setText("下拉刷新");                break;            case RELEASE_REFRESH:                // 做动画, 改标题                mArrowView.startAnimation(rotateUpAnim);                mTitleText.setText("释放刷新");                break;            case REFRESHING:                mArrowView.clearAnimation();                mArrowView.setVisibility(View.INVISIBLE);                pb.setVisibility(View.VISIBLE);                mTitleText.setText("正在刷新中...");                if(mListener != null){                    mListener.onRefresh(); // 通知调用者, 让其到网络加载更多数据.                }                break;        }    }

3.为调用者提供接口用来加载 需要加载的数据
    public interface OnRefreshListener{        void onRefresh(); // 下拉刷新        void onLoadMore();// 加载更多    }    public void setRefreshListener(OnRefreshListener mListener) {        this.mListener = mListener;    }}



这样我们的自定义listview就完成了

0 0