Android实现ListView下拉刷新和上拉加载更多的思路

1、继承ListView类来扩展实现

2、ListView类可以通过addFooterView和addHeaderView方法来添加列表的头和尾,可以用来实现一些拉动的动画和提示

3、重载public boolean onTouchEvent(MotionEvent ev)方法,可以监听到触摸点的点下、滑动和离开的操作,用来判断滑动的方向

4、 public void onScrollStateChanged(AbsListView view, int scrollState)事件,监控列表的滚动状态

import java.text.SimpleDateFormat;

import java.util.Date;



import android.content.Context;

import android.util.AttributeSet;

import android.view.MotionEvent;

import android.view.View;

import android.view.animation.Animation;

import android.view.animation.RotateAnimation;

import android.widget.AbsListView;

import android.widget.AbsListView.OnScrollListener;

import android.widget.ImageView;

import android.widget.LinearLayout;

import android.widget.ListView;

import android.widget.ProgressBar;

import android.widget.TextView;



/**

 * 自定义ListView,下拉刷新、上拉自动加载更多

 */

public class PullListView extends ListView implements OnScrollListener {



    private final int PULL_DOWN_REFRESH = 0;//下拉状态

    private final int RELEASE_REFRESH = 1;//松开状态

    private final int REFRESHING = 2;//刷新中状态

    private int currentState = PULL_DOWN_REFRESH;

    private int mListViewOnScreenY = -1;//listview的y坐标

    private int downY = -1;//触摸点的y坐标



    private boolean isLoadingMore = false;

    private boolean isEnabledPullDownRefresh = false;

    private boolean isEnabledLoadMore = false;

    private OnPullDownRefresh mOnPullDownRefresh;



    //头布局、脚布局及高度

    private View mFootView;

    private LinearLayout mHeaderView;

    private int mFooterViewHeight;

    private int mPullDownHeaderViewHeight;



    //mHeaderView中组件及动画

    private View mCustomHeaderView;//用户自定义头布局

    private View mPullDownHeader;//下拉刷新头布局

    private RotateAnimation upAnimation,downAnimation;

    private ImageView ivArrow;

    private ProgressBar mProgressBar;

    private TextView tv_statue,tv_time;





    public PullListView(Context context) {

        this(context, null);

    }



    public PullListView(Context context, AttributeSet attrs) {

        this(context, attrs, 0);

    }



    public PullListView(Context context, AttributeSet attrs, int defStyle) {

        super(context, attrs, defStyle);

        initPullDownHeaderView();

        initLoadMoreFooterView();

    }



    private void initLoadMoreFooterView() {

        //加载更多的布局文件

        mFootView = View.inflate(getContext(), R.layout.pull_listview_footer,

                null);

        mFootView.measure(0, 0);//测量

        mFooterViewHeight = mFootView.getMeasuredHeight();

        //隐藏脚布局

        mFootView.setPadding(0,-mFooterViewHeight,0,0);

        addFooterView(mFootView);

        setOnScrollListener(this);

    }



    private void initPullDownHeaderView() {

        //下拉刷新的布局文件

        mHeaderView = (LinearLayout) View.inflate(getContext(),

                R.layout.pull_listview_header, null);

        mPullDownHeader = mHeaderView

                .findViewById(R.id.ll_refresh_pull_down_header);

        ivArrow = (ImageView) mHeaderView

                .findViewById(R.id.iv_refresh_header_arrow);

        mProgressBar = (ProgressBar) mHeaderView

                .findViewById(R.id.pb_refresh_header);

        tv_statue = (TextView) mHeaderView

                .findViewById(R.id.tv_refresh_header_status);

        tv_time = (TextView) mHeaderView

                .findViewById(R.id.tv_refresh_header_time);

        mPullDownHeader.measure(0, 0);//测量

        mPullDownHeaderViewHeight = mPullDownHeader.getMeasuredHeight();

        //隐藏头布局

        mPullDownHeader.setPadding(0, -mPullDownHeaderViewHeight, 0, 0);

        addHeaderView(mHeaderView);

        initAnimation();

    }



    /**

     * 添加额外的头布局,比如轮播图

     * @param v 自定义头布局

     */

    public void addListViewCustomHeaderView(View v) {

        mCustomHeaderView = v;

        mHeaderView.addView(mCustomHeaderView);

    }



    @Override

    public boolean onTouchEvent(MotionEvent ev) {

        switch (ev.getAction()) {

            case MotionEvent.ACTION_DOWN:

                downY = (int) ev.getY();

                break;

            case MotionEvent.ACTION_MOVE:

                if (downY == -1)//-1是初始值

                    downY = (int) ev.getY();

                //是否启用下拉刷新

                if (!isEnabledPullDownRefresh)

                    break;

                if (currentState == REFRESHING)

                    break;

                //解决用户添加header与下拉刷新header的冲突

                if (mCustomHeaderView != null) {

                    int[] location = new int[2];

                    if (mListViewOnScreenY == -1) {

                        this.getLocationOnScreen(location);//获取控件在屏幕的xy坐标 左上角的

                        mListViewOnScreenY = location[1];

                    }

                    mCustomHeaderView.getLocationOnScreen(location);

                    if (location[1] < mListViewOnScreenY) {

                        break;

                    }

                }



                int moveY = (int) ev.getY();

                int diffY = (moveY - downY)/2;//当前的点和上一次的点的距离

                if (diffY > 0 && getFirstVisiblePosition() == 0) {//下拉操作 并且listview第一个item可见

                    int paddingTop = -mPullDownHeaderViewHeight + diffY;//距离顶部的距离

                    if (paddingTop < 0 && currentState != PULL_DOWN_REFRESH) {

                        //当前没有完全显示且当前状态为松开刷新,进入下拉刷新

                        currentState = PULL_DOWN_REFRESH;

                        refreshPullDownState();

                    } else if (paddingTop > 0 && currentState != RELEASE_REFRESH) {

                        //当前完全显示且当前状态为下拉刷新,进入松开刷新

                        currentState = RELEASE_REFRESH;

                        refreshPullDownState();

                    }

                    mPullDownHeader.setPadding(0, paddingTop, 0, 0);

                    return true;

                }else if(diffY < 0 && getLastVisiblePosition() == getCount()-1){//上拉操作 并且最后一个item可见

                    //脚布局可向上滑动

                    mFootView.setPadding(0,0,0,0);

                }

                break;

            case MotionEvent.ACTION_UP:

                downY = -1;

                if (currentState == PULL_DOWN_REFRESH) {

                    //隐藏header

                    mPullDownHeader.setPadding(0, -mPullDownHeaderViewHeight, 0, 0);

                } else if (currentState == RELEASE_REFRESH) {

                    currentState = REFRESHING;

                    refreshPullDownState();

                    mPullDownHeader.setPadding(0, 0, 0, 0);

                    //回调刷新方法

                    if (mOnPullDownRefresh != null) {

                        mOnPullDownRefresh.onPullDownRefresh();

                    }

                }

                break;

        }

        return super.onTouchEvent(ev);

    }



    /**

     * 隐藏头布局或脚布局并重置控件

     */

    public void OnRefreshDataFinish() {

        if (isLoadingMore) {

            isLoadingMore = false;

            mFootView.setPadding(0,-mFooterViewHeight,0,0);

        } else {

            ivArrow.setVisibility(View.VISIBLE);

            mProgressBar.setVisibility(View.INVISIBLE);

            tv_statue.setText("下拉刷新");

            tv_time.setText("最后刷新时间:" + getCurrentTime());

            mPullDownHeader.setPadding(0, -mPullDownHeaderViewHeight, 0, 0);

            currentState = PULL_DOWN_REFRESH;



        }

    }



    private String getCurrentTime() {

        SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");

        return format.format(new Date());

    }



    private void refreshPullDownState() {

        switch (currentState) {

                case PULL_DOWN_REFRESH:

                    ivArrow.startAnimation(downAnimation);

                    tv_statue.setText("下拉刷新");

                    break;

                case RELEASE_REFRESH:

                    ivArrow.startAnimation(upAnimation);

                    tv_statue.setText("松开刷新");

                    break;

                case REFRESHING:

                    ivArrow.clearAnimation();

                    ivArrow.setVisibility(View.INVISIBLE);

                    mProgressBar.setVisibility(View.VISIBLE);

                    tv_statue.setText("正在刷新");

                    break;

                default:

                break;

        }

    }



    /**

     * 箭头旋转动画

     */

    private void initAnimation() {

        upAnimation = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF,

                0.5f, Animation.RELATIVE_TO_SELF, 0.5f);

        upAnimation.setDuration(200);

        upAnimation.setFillAfter(true);



        downAnimation = new RotateAnimation(-180, -360,

                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,

                0.5f);

        downAnimation.setDuration(200);

        downAnimation.setFillAfter(true);

    }



    /**

     * 回调方法,用于刷新数据及加载更多

     * @param listener

     */

    public void setOnPullDownRefresh(OnPullDownRefresh listener) {

        this.mOnPullDownRefresh = listener;

    }



    public interface OnPullDownRefresh {

        public void onPullDownRefresh();

        public void onLoadingMore();

    }

    /*

    下拉加载更多通过onScrollStateChanged事件来实现

     */

    @Override

    public void onScrollStateChanged(AbsListView view, int scrollState) {

        if (!isEnabledLoadMore) {

            return;

        }

        //listView停止状态或惯性滑动状态

        if (scrollState == SCROLL_STATE_IDLE

                || scrollState == SCROLL_STATE_FLING) {

            //listView已到达最底部

            if ((getLastVisiblePosition() == getCount() - 1) && !isLoadingMore) {

                isLoadingMore = true;

                //展示脚布局

                mFootView.setPadding(0, 0, 0, 0);

                setSelection(getCount());

                if (mOnPullDownRefresh != null) {

                    mOnPullDownRefresh.onLoadingMore();

                }

            }

        }

    }



    @Override

    public void onScroll(AbsListView view, int firstVisibleItem,

                         int visibleItemCount, int totalItemCount) {



    }



    /**

     * 是否启用下拉刷新

     * @param isEnable

     */

    public void setEnabledPullDownRefresh(boolean isEnable) {

        isEnabledPullDownRefresh = isEnable;

    }



    /**

     * 是否启用加载更多

     * @param isEnable

     */

    public void setEnabledLoadMore(boolean isEnable) {

        isEnabledLoadMore = isEnable;

    }

}

 

你可能感兴趣的:(ListView)