下拉刷新和上拉加载的ListView-MutilListView

来源:互联网 发布:微信改单是什么软件 编辑:程序博客网 时间:2024/05/16 19:33
public class LoadListView extends ListView implements OnScrollListener {    private int firstItem;// 当前可以见第一个Item的位置    private int lastItem;// 当前可以见最后一个Item的位置    private int totalItemCount;// list总数量    private OnLoadListener mListener;// 回调接口    private boolean isLoading = false;;// 是否正在加载    private View footer;// 底布局文件    private View head;// 头布局文件    private int headHeigth;// 布局高度    // 下拉刷新相关    private boolean isRemark;// 是否在第一个Item按下    private int startY;// 滑动开始前的Y值    private int state;// 当前状态    private final int NONE = 0;// 正常状态    private final int PULL = 1;// 提示下拉状态    private final int RELESE = 2;// 提示释放状态    private final int REFLASHING = 3;// 刷新状态状态    private int scrollState;// 当前listview的状态    public LoadListView(Context context) {        super(context);        initView(context);    }    public LoadListView(Context context, AttributeSet attrs) {        super(context, attrs);        initView(context);    }    public LoadListView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        initView(context);    }    private void initView(Context context) {        LayoutInflater mInflater = LayoutInflater.from(context);        // 底布局操作相关        footer = mInflater.inflate(R.layout.listiview_footer, null);        footer.findViewById(R.id.footer_ll_layout).setVisibility(View.GONE);        this.addFooterView(footer);        head = mInflater.inflate(R.layout.listview_head, null);        // 通知父布局Head占用的大小        measureHead(head);        // 获取高度        headHeigth = head.getMeasuredHeight();        // 设置头布局为高度的负值而隐藏        setHeaderPaddingTop(-headHeigth);        this.addHeaderView(head);        this.setOnScrollListener(this);    }    /**     * 通知父布局Head占用的大小 (此处本人也未彻底搞懂)     *      * @param view     */    private void measureHead(View view) {        ViewGroup.LayoutParams p = view.getLayoutParams();        if (p == null) {            p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,                    ViewGroup.LayoutParams.WRAP_CONTENT);        }        int width = ViewGroup.getChildMeasureSpec(0, 0, p.width);        int height;        int tempHeight = p.height;        if (tempHeight > 0) {            height = MeasureSpec.makeMeasureSpec(tempHeight,                    MeasureSpec.EXACTLY);        } else {            height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);        }        view.measure(width, height);    }    /**     * 设置Head布局的上边距,以达到隐藏头布局的目的     *      * @param paddingTop     */    private void setHeaderPaddingTop(int paddingTop) {        head.setPadding(head.getPaddingLeft(), paddingTop,                head.getPaddingRight(), head.getPaddingBottom());        // 刷新View的方法        head.invalidate();    }    /**     * 下拉刷新 监听手指的滑动状态     */    @Override    public boolean onTouchEvent(MotionEvent ev) {        switch (ev.getAction()) {        case MotionEvent.ACTION_DOWN:            // 如果实在顶部开始滑动 则记录当前y的位置,后面用来计算滑动的距离            if (firstItem == 0) {                startY = (int) ev.getY();                isRemark = true;            }            break;        case MotionEvent.ACTION_MOVE:            onMove(ev);// 判断手指滑动过程中的动作            break;        case MotionEvent.ACTION_UP:            // 手指抬起后用来判断是否到达刷新数据要求的目的            if (state == RELESE) {                state = REFLASHING;                // 加载最新数据                reflushData();            } else if (state == PULL || state == NONE) {                state = NONE;                isRemark = false;                reflushViewByState();            }            break;        }        return super.onTouchEvent(ev);    }    private void onMove(MotionEvent ev) {        if (!isRemark) {            return;        }        int tempY = (int) ev.getY();        Log.v("y", tempY + "");        // 滑动的距离        int distance = tempY - startY;        // 头布局慢慢显示出来的宽度        int topPadding = distance - headHeigth;        switch (state) {        case NONE:            if (distance > 0) {                state = PULL;                reflushViewByState();            } else {            }            break;        case PULL:            // 绘制当前 拉动过程的头布局            setHeaderPaddingTop(topPadding);            // 如果距离大于头布局+100 dp且ListView在滑动过程中            if (distance > headHeigth + 100                    && scrollState == SCROLL_STATE_TOUCH_SCROLL) {                state = RELESE;                reflushViewByState();            }            break;        case RELESE:            // 绘制当前 拉动过程的头布局            setHeaderPaddingTop(topPadding);            if (distance < headHeigth + 100) {                state = PULL;                reflushViewByState();            } else if (distance <= 0) {                state = NONE;                isRemark = false;                reflushViewByState();            } else if (distance > 500) {            }            break;        }    }    /**     * 刷新数据的执行方法     */    private void reflushData() {        state = REFLASHING;        isRemark = false;        reflushViewByState();        mListener.onRefresh();    }    /**     * 根据当前状态改变界面显示     *      * @param state     */    private void reflushViewByState() {        TextView tip = (TextView) head.findViewById(R.id.head_tv_tips);        ImageView pic = (ImageView) head.findViewById(R.id.head_iv_pic);        ProgressBar pb = (ProgressBar) head.findViewById(R.id.head_pb_progress);        RotateAnimation anim = new RotateAnimation(0, 180,                RotateAnimation.RELATIVE_TO_SELF, 0.5f,                RotateAnimation.RELATIVE_TO_SELF, 0.5f);        anim.setDuration(500);        anim.setFillAfter(true);        RotateAnimation anim1 = new RotateAnimation(180, 0,                RotateAnimation.RELATIVE_TO_SELF, 0.5f,                RotateAnimation.RELATIVE_TO_SELF, 0.5f);        anim1.setDuration(500);        anim1.setFillAfter(true);        switch (state) {        case NONE:            setHeaderPaddingTop(-headHeigth);            break;        case PULL:            tip.setText("下拉可以刷新!");            pic.setVisibility(View.VISIBLE);            pb.setVisibility(View.GONE);            // 设置相关动画            pic.clearAnimation();            pic.setAnimation(anim);            break;        case RELESE:            tip.setText("松开可以刷新!");            pic.setVisibility(View.VISIBLE);            pb.setVisibility(View.GONE);            // 设置相关动画            pic.setAnimation(anim1);            break;        case REFLASHING:            setHeaderPaddingTop(0);            tip.setText("正在刷新!");            pic.clearAnimation();// 这里一定要执行清楚动画,不然图片无法隐藏            pic.setVisibility(View.GONE);            pb.setVisibility(View.VISIBLE);            break;        }    }    // 下拉刷新完成回调    public void reflushCompleted() {        state = NONE;        isRemark = false;        reflushViewByState();    }    // 分页加载完成回调    public void flushCompleted() {        isLoading = false;        footer.findViewById(R.id.footer_ll_layout).setVisibility(View.GONE);    }    public void setOnLoadListener(OnLoadListener listener) {        this.mListener = listener;    }    public interface OnLoadListener {        // 分页加载        void onLoadMore();        // 下拉刷新        void onRefresh();    }    @Override    public void onScrollStateChanged(AbsListView view, int scrollState) {        if (lastItem == totalItemCount && SCROLL_STATE_IDLE == scrollState) {            if (!isLoading) {                footer.findViewById(R.id.footer_ll_layout).setVisibility(                        View.VISIBLE);                mListener.onLoadMore();                isLoading = true;            }        }        this.scrollState = scrollState;    }    @Override    public void onScroll(AbsListView view, int firstVisibleItem,            int visibleItemCount, int totalItemCount) {        this.lastItem = firstVisibleItem + visibleItemCount;        this.totalItemCount = totalItemCount;        this.firstItem = firstVisibleItem;    }}

以上是实现了了下拉刷新和上拉加载第二页的ListView代码。
欢迎各位指出错误,大家多多指教。

0 0
原创粉丝点击