您的位置:首页 > 移动开发 > Android开发

Android自定义控件-ListViewForRefresh

2015-05-04 16:28 357 查看

欢迎加入QQ群探讨Android开发技术—>QQ群【软件开发-Android】:314896948

功能描述:

支持自定义顶部视图,以视图+ListView方式展示

支持下拉刷新,可选择打开或关闭

支持加载更多,可选择打开或关闭

使用步骤:

调用addCustomHeadView添加顶部视图,如轮播广告图等。

[code]mListView.addCustomHeadView(View.inflate(this, R.layout.view_custom, null));


调用enablePullDownRefresh和enableLoadMoreRefresh分别设置打开或关闭下拉刷新、加载更多.

[code]mListView.enablePullDownRefresh(true);
mListView.enableLoadMoreRefresh(true);


调用setOnRefreshListener设置监听,在回调接口中实现数据加载,数据加载完成发送消息通知视图刷新.

[code]mListView.setOnRefreshListener(mListener);


监听mListener如下:

[code]private onRefreshListener mListener = new onRefreshListener() {
    @Override
    public void onPullDownRefresh() {
        // 异步加载数据
        new Thread(new Runnable() {
            @Override
            public void run() {
                SystemClock.sleep(3000);
                mData.add(0, "test--data-->newdata");
                mHandler.obtainMessage(WHAT_DATA_LOAD_FINISH).sendToTarget();
            }
        }).start();
    }

    @Override
    public void onLoadMoreRefresh() {
        // 异步加载数据
        new Thread(new Runnable() {
            @Override
            public void run() {
                SystemClock.sleep(3000);
                mData.add("test--data-->newdata");
                mHandler.obtainMessage(WHAT_DATA_LOAD_FINISH).sendToTarget();
            }
        }).start();
    }
};


接收到消息后关闭刷新视图

[code]private Handler mHandler = new Handler(Looper.getMainLooper()) {
    public void handleMessage(android.os.Message msg) {
        switch (msg.what) {
        case WHAT_DATA_LOAD_FINISH:
            mListView.FinishRefesh();
            mAdapter.notifyDataSetChanged();
            break;
        }
    };
}


效果图:

下拉刷新



加载更多



直接上代码—>自定义RefreshListView code:

[code]package com.leo.demo;

import java.text.SimpleDateFormat;
import java.util.Date;
import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
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;

public class RefreshListView extends ListView implements OnScrollListener {
    private static final String TAG = "RefreshListView";
    private static final Boolean DEBUG = false;
    /** 头控件整个布局(包含下拉刷新和用户自定义需要添加的控件) */
    private LinearLayout mHeadView;
    /** 下拉刷新控件 */
    private View mPullDownHeadView;
    /** 下拉刷新布局高度 */
    private int mPullDownHeadViewHeigth;
    /** 触摸按下的Y坐标 */
    private int downY = -1;
    /** 下拉刷新状态 */
    private static final int STATE_PULL_DOWN_REFRESH = 0x000;
    /** 释放刷新状态 */
    private static final int STATE_RELEASE_REFRESH = 0x001;
    /** 正在刷新状态 */
    private static final int STATE_REFRESHING = 0x002;
    /** 当前刷新状态 */
    private int currentState = STATE_PULL_DOWN_REFRESH;// 默认是下拉刷新状态
    /** 向上旋转动画 */
    private RotateAnimation upRa;
    /** 向下旋转动画 */
    private RotateAnimation downRa;
    /** 下拉刷新 动画箭头 */
    private ImageView mRefreshArrow;
    /** 下拉刷新 进度环 */
    private ProgressBar mRefreshProgressBar;
    /** 下拉刷新 状态文字显示 */
    private TextView mRefreshState;
    /** 下拉刷新 上次刷新时间 */
    private TextView mRefreshDate;
    /** 用户自定义的需要加在头部的view */
    private View mCustomView;
    /** ListView左上角在屏幕上的位置Y */
    private int mListViewHeigthOnScreen = -1;
    /** 刷新列表回调监听器 */
    private onRefreshListener mListener;
    /** 底部加载更多控件 */
    private View mLoadMoreView;
    /** 底部加载更多控件的测量高度 */
    private int mLoadMoreViewHeight;
    /** 是否加载更多 */
    private boolean isLoadMore = false;
    /** 是否启用下拉刷新 (默认关闭下拉刷新) */
    private boolean isEnablePullDownRefresh = false;
    /** 是否启用加载更多 (默认关闭加载更多) */
    private boolean isEnableLoadMoreRefresh = false;

    public RefreshListView(Context context) {
        super(context);
        initHeadView();
        initFootView();
    }

    public RefreshListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initHeadView();
        initFootView();
    }

    public RefreshListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initHeadView();
        initFootView();
    }

    /** 初始化底部加载更多控件 */
    private void initFootView() {
        mLoadMoreView = View.inflate(getContext(), R.layout.refresh_load_more, null);
        mLoadMoreView.measure(0, 0);
        mLoadMoreViewHeight = mLoadMoreView.getMeasuredHeight();
        mLoadMoreView.setPadding(0, -mLoadMoreViewHeight, 0, 0);
        this.addFooterView(mLoadMoreView);
        this.setOnScrollListener(this);// 给当前Listview设置一个滑动的监听事件
    }

    /** 初始化头部下拉刷新控件 */
    private void initHeadView() {
        mHeadView = (LinearLayout) View.inflate(getContext(), R.layout.refresh_pull_down, null);
        mPullDownHeadView = mHeadView.findViewById(R.id.ll_pull_down_refresh_root);
        mRefreshArrow = (ImageView) mHeadView.findViewById(R.id.iv_pull_dowd_refresh_arrow);
        mRefreshProgressBar = (ProgressBar) mHeadView.findViewById(R.id.pb_pull_dowd_refresh_progressbar);
        mRefreshState = (TextView) mHeadView.findViewById(R.id.tv_pull_dowd_refresh_state_desc);
        mRefreshDate = (TextView) mHeadView.findViewById(R.id.tv_pull_dowd_refresh_date);

        mRefreshDate.setText("上次刷新:" + getCurentTime());// 设置默认显示上次刷新时间
        mPullDownHeadView.measure(0, 0);// 测量,以获取测量高度
        mPullDownHeadViewHeigth = mPullDownHeadView.getMeasuredHeight();
        mPullDownHeadView.setPadding(0, -mPullDownHeadViewHeigth, 0, 0);// 默认隐藏头控件
        this.addHeaderView(mHeadView);// 添加到头控件中
        initAnimation();// 初始化箭头动画
    }

    /** 初始化头部控件中箭头的旋转动画 */
    private void initAnimation() {
        upRa = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        upRa.setDuration(500);
        upRa.setFillAfter(true);

        downRa = new RotateAnimation(-180, -360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        downRa.setDuration(500);
        downRa.setFillAfter(true);
    }

    /** 在头部控件内添加用户自定义的view */
    public void addCustomHeadView(View v) {
        this.mCustomView = v;
        mHeadView.addView(v);
    }

    @SuppressLint("ClickableViewAccessibility")
    @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) {
                downY = (int) ev.getY();
            }
            // 如果是没有启用下拉刷新 则跳出循环
            if (!isEnablePullDownRefresh) {
                break;
            }
            // 如果当前是正在刷新中,则跳出循环
            if (currentState == STATE_REFRESHING) {
                break;
            }
            // 判断添加的顶部View是否完全显示了, 如果没有完全显示,跳出switch语句, 执行父元素的touch事件.
            if (mCustomView != null) {
                int[] location = new int[2];// 0位是x轴的值, 1位是y轴的值
                // 获取Listview在屏幕中y轴的值.
                if (mListViewHeigthOnScreen == -1) {
                    this.getLocationOnScreen(location);
                    mListViewHeigthOnScreen = location[1];
                    showLog("ListView--Y:" + mListViewHeigthOnScreen);
                }
                // 获取mCustomHeaderView在屏幕y轴的值.
                mCustomView.getLocationOnScreen(location);
                int mCustomViewHeigthOnScreen = location[1];
                showLog("mCustomView--Y:" + mCustomViewHeigthOnScreen);

                if (mCustomViewHeigthOnScreen < mListViewHeigthOnScreen) {
                    break;// 未完全显示自定义的view,jump out
                }
            }

            int moveY = (int) ev.getY();
            int dy = moveY - downY;
            if (dy > 0 && getFirstVisiblePosition() == 0) {
                // 如果是下拉,并且当前第一个可视条目是列表中的第一个,可以拉出头控件
                int paddingTop = -mPullDownHeadViewHeigth + dy;
                if (paddingTop > 0 && currentState != STATE_RELEASE_REFRESH) {
                    // 完全拉出来了,并且当前状态不是释放刷新,则切换到释放刷新状态
                    currentState = STATE_RELEASE_REFRESH;
                    changeRefreshState();
                } else if (paddingTop < 0 && currentState != STATE_PULL_DOWN_REFRESH) {
                    // 没有完全拉出来,并且当前状态不是下拉刷新,则切换到下拉刷新状态
                    currentState = STATE_PULL_DOWN_REFRESH;
                    changeRefreshState();
                }
                mPullDownHeadView.setPadding(0, paddingTop, 0, 0);
                return true;
            }
            break;

        case MotionEvent.ACTION_UP:
            downY = -1;
            if (currentState == STATE_PULL_DOWN_REFRESH) {
                // 如果当前是下拉刷新状态,则直接隐藏
                mPullDownHeadView.setPadding(0, -mPullDownHeadViewHeigth, 0, 0);
            } else if (currentState == STATE_RELEASE_REFRESH) {
                // 如果当前是释放刷新状态,则切换到正在刷新
                currentState = STATE_REFRESHING;
                changeRefreshState();
                mPullDownHeadView.setPadding(0, 0, 0, 0);
                // 回调用户处理操作
                if (mListener != null) {
                    mListener.onPullDownRefresh();
                }
            }
            break;
        }
        return super.onTouchEvent(ev);
    }

    /** 切换当前头控件显示的刷新状态 */
    private void changeRefreshState() {
        switch (currentState) {
        case STATE_PULL_DOWN_REFRESH: // 下拉刷新
            mRefreshArrow.startAnimation(downRa);
            mRefreshState.setText("下拉刷新");
            break;
        case STATE_RELEASE_REFRESH: // 释放刷新
            mRefreshArrow.startAnimation(upRa);
            mRefreshState.setText("释放刷新");
            break;
        case STATE_REFRESHING: // 正在刷新
            mRefreshArrow.clearAnimation();
            mRefreshArrow.setVisibility(View.INVISIBLE);
            mRefreshProgressBar.setVisibility(View.VISIBLE);
            mRefreshState.setText("正在刷新中...");
            break;
        }
    }

    /** 当刷新完成后调用此方法,隐藏头部上拉刷新和底部加在更多 */
    public void FinishRefesh() {
        if (isLoadMore) {
            // 隐藏加载更多,复位变量
            isLoadMore = false;
            mLoadMoreView.setPadding(0, -mLoadMoreViewHeight, 0, 0);
        } else {
            // 隐藏上拉刷新,复位变量
            mPullDownHeadView.setPadding(0, -mPullDownHeadViewHeigth, 0, 0);
            currentState = STATE_PULL_DOWN_REFRESH;
            mRefreshState.setText("下拉刷新");
            mRefreshArrow.setVisibility(View.VISIBLE);
            mRefreshProgressBar.setVisibility(View.INVISIBLE);
            mRefreshDate.setText("上次刷新:" + getCurentTime());
        }
    }

    /** 获取当前时间, 格式为: 1990-09-09 09:09:09 */
    @SuppressLint("SimpleDateFormat")
    private String getCurentTime() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return format.format(new Date());
    }

    /** 下拉刷新回调接口 */
    public interface onRefreshListener {
        /** 下拉刷新 加载数据处理 */
        void onPullDownRefresh();

        /** 加载更多 加载数据处理 */
        void onLoadMoreRefresh();
    }

    /** 设置下拉刷新回调监听器 */
    public void setOnRefreshListener(onRefreshListener listener) {
        this.mListener = listener;
    }

    /** 监听滑动状态,设置加载更多 */
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        if (!isEnableLoadMoreRefresh) {
            return;// false 关闭加载更多,直接返回
        }
        if (currentState == SCROLL_STATE_IDLE || currentState == SCROLL_STATE_FLING) {
            if (getLastVisiblePosition() == getCount() - 1 && !isLoadMore) {
                // 滑动到listview最后一个条目,显示加载更多
                isLoadMore = true;
                mLoadMoreView.setPadding(0, 0, 0, 0);// 显示加载更多控件
                setSelection(getCount());// 显示最后一个条目
                // 处理用户的回调操作
                if (mListener != null) {
                    mListener.onLoadMoreRefresh();
                }
            }
        }
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

    }

    /** 是否启用下拉刷新 */
    public void enablePullDownRefresh(boolean isEnable) {
        this.isEnablePullDownRefresh = isEnable;
    }

    /** 是否启用加载更多 */
    public void enableLoadMoreRefresh(boolean isEnable) {
        this.isEnableLoadMoreRefresh = isEnable;
    }

    /** 打印log信息 */
    private static void showLog(String msg) {
        if (DEBUG) {
            Log.e(TAG, msg);
        }
    }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: