CustomListView

https://yunpan.cn/cR2z5qTS6F9ka  访问密码 0507

下载图片

创建CustomListView

package tests.bwie.com.mylistview;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

/**
 * ListView下拉刷新和加载更多<p>
 *
 * <strong>变更说明:</strong>
 * <p>默认如果设置了OnRefreshListener接口和OnLoadMoreListener接口,<br>并且不为null,则打开这两个功能了。
 * <p>剩余两个Flag:mIsAutoLoadMore(是否自动加载更多)和
 * <br>mIsMoveToFirstItemAfterRefresh(下拉刷新后是否显示第一条Item)
 *
 * <p><strong>有改进意见,请发送到俺的邮箱哈~ 多谢各位小伙伴了!^_^</strong>
 *
 * @date 2013-11-11 下午10:09:26
 * @change JohnWatson
 * @mail [email protected]
 * @version 1.0
 */
public class CustomListView extends ListView implements OnScrollListener {

    /**  显示格式化日期模板   */
    private final static String DATE_FORMAT_STR = "yyyy年MM月dd日 HH:mm";

    /**  实际的padding的距离与界面上偏移距离的比例   */
    private final static int RATIO = 3;

    private final static int RELEASE_TO_REFRESH = 0;
    private final static int PULL_TO_REFRESH = 1;
    private final static int REFRESHING = 2;
    private final static int DONE = 3;
    private final static int LOADING = 4;

    /**  加载中   */
    private final static int ENDINT_LOADING = 1;
    /**  手动完成刷新   */
    private final static int ENDINT_MANUAL_LOAD_DONE = 2;
    /**  自动完成刷新   */
    private final static int ENDINT_AUTO_LOAD_DONE = 3;

    /**    0:RELEASE_TO_REFRESH;
     * <p> 1:PULL_To_REFRESH;
     * <p> 2:REFRESHING;
     * <p> 3:DONE;
     * <p> 4:LOADING */
    private int mHeadState;
    /**    0:完成/等待刷新 ;
     * <p> 1:加载中  */
    private int mEndState;

    // ================================= 功能设置Flag ================================

    /**  可以加载更多?   */
    private boolean mCanLoadMore = false;
    /**  可以下拉刷新?   */
    private boolean mCanRefresh = false;
    /**  可以自动加载更多吗?(注意,先判断是否有加载更多,如果没有,这个flag也没有意义)   */
    private boolean mIsAutoLoadMore = true;
    /** 下拉刷新后是否显示第一条Item    */
    private boolean mIsMoveToFirstItemAfterRefresh = false;

    public boolean isCanLoadMore() {
        return mCanLoadMore;
    }

    public void setCanLoadMore(boolean pCanLoadMore) {
        mCanLoadMore = pCanLoadMore;
        if(mCanLoadMore && getFooterViewsCount() == 0){
            addFooterView();
        }
    }

    public boolean isCanRefresh() {
        return mCanRefresh;
    }

    public void setCanRefresh(boolean pCanRefresh) {
        mCanRefresh = pCanRefresh;
    }

    public boolean isAutoLoadMore() {
        return mIsAutoLoadMore;
    }

    public void setAutoLoadMore(boolean pIsAutoLoadMore) {
        mIsAutoLoadMore = pIsAutoLoadMore;
    }

    public boolean isMoveToFirstItemAfterRefresh() {
        return mIsMoveToFirstItemAfterRefresh;
    }

    public void setMoveToFirstItemAfterRefresh(
            boolean pIsMoveToFirstItemAfterRefresh) {
        mIsMoveToFirstItemAfterRefresh = pIsMoveToFirstItemAfterRefresh;
    }

    // ============================================================================

    private LayoutInflater mInflater;

    private LinearLayout mHeadView;
    private TextView mTipsTextView;
    private TextView mLastUpdatedTextView;
    private ImageView mArrowImageView;
    private ProgressBar mProgressBar;

    private View mEndRootView;
    private ProgressBar mEndLoadProgressBar;
    private TextView mEndLoadTipsTextView;

    /**  headView动画   */
    private RotateAnimation mArrowAnim;
    /**  headView反转动画   */
    private RotateAnimation mArrowReverseAnim;

    /** 用于保证startY的值在一个完整的touch事件中只被记录一次    */
    private boolean mIsRecored;

    private int mHeadViewWidth;
    private int mHeadViewHeight;

    private int mStartY;
    private boolean mIsBack;

    private int mFirstItemIndex;
    private int mLastItemIndex;
    private int mCount;
    private boolean mEnoughCount;//足够数量充满屏幕? 

    private OnRefreshListener mRefreshListener;
    private OnLoadMoreListener mLoadMoreListener;

    public CustomListView(Context pContext, AttributeSet pAttrs) {
        super(pContext, pAttrs);
        init(pContext);
    }

    public CustomListView(Context pContext) {
        super(pContext);
        init(pContext);
    }

    public CustomListView(Context pContext, AttributeSet pAttrs, int pDefStyle) {
        super(pContext, pAttrs, pDefStyle);
        init(pContext);
    }

    /**
     * 初始化操作
     * @param pContext
     * @date 2013-11-20 下午4:10:46
     * @change JohnWatson
     * @version 1.0
     */
    private void init(Context pContext) {
        setCacheColorHint(pContext.getResources().getColor(R.color.common_color_transparent));
        mInflater = LayoutInflater.from(pContext);

        addHeadView();

        setOnScrollListener(this);

        initPullImageAnimation(0);
    }

    /**
     * 添加下拉刷新的HeadView
     * @date 2013-11-11 下午9:48:26
     * @change JohnWatson
     * @version 1.0
     */
    private void addHeadView() {
        mHeadView = (LinearLayout) mInflater.inflate(R.layout.head, null);

        mArrowImageView = (ImageView) mHeadView
                .findViewById(R.id.head_arrowImageView);
        mArrowImageView.setMinimumWidth(70);
        mArrowImageView.setMinimumHeight(50);
        mProgressBar = (ProgressBar) mHeadView
                .findViewById(R.id.head_progressBar);
        mTipsTextView = (TextView) mHeadView.findViewById(
                R.id.head_tipsTextView);
        mLastUpdatedTextView = (TextView) mHeadView
                .findViewById(R.id.head_lastUpdatedTextView);

        measureView(mHeadView);
        mHeadViewHeight = mHeadView.getMeasuredHeight();
        mHeadViewWidth = mHeadView.getMeasuredWidth();

        mHeadView.setPadding(0, -1 * mHeadViewHeight, 0, 0);
        mHeadView.invalidate();

        Log.v("size", "width:" + mHeadViewWidth + " height:"
                + mHeadViewHeight);

        addHeaderView(mHeadView, null, false);

        mHeadState = DONE;
    }

    /**
     * 添加加载更多FootView
     * @date 2013-11-11 下午9:52:37
     * @change JohnWatson
     * @version 1.0
     */
    private void addFooterView() {
        mEndRootView = mInflater.inflate(R.layout.listfooter_more, null);
        mEndRootView.setVisibility(View.VISIBLE);
        mEndLoadProgressBar = (ProgressBar) mEndRootView
                .findViewById(R.id.pull_to_refresh_progress);
        mEndLoadTipsTextView = (TextView) mEndRootView.findViewById(R.id.load_more);
        mEndRootView.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                if(mCanLoadMore){
                    if(mCanRefresh){
                        // 当可以下拉刷新时,如果FootView没有正在加载,并且HeadView没有正在刷新,才可以点击加载更多。
                        if(mEndState != ENDINT_LOADING && mHeadState != REFRESHING){
                            mEndState = ENDINT_LOADING;
                            onLoadMore();
                        }
                    }else if(mEndState != ENDINT_LOADING){
                        // 当不能下拉刷新时,FootView不正在加载时,才可以点击加载更多。
                        mEndState = ENDINT_LOADING;
                        onLoadMore();
                    }
                }
            }
        });

        addFooterView(mEndRootView);

        if(mIsAutoLoadMore){
            mEndState = ENDINT_AUTO_LOAD_DONE;
        }else{
            mEndState = ENDINT_MANUAL_LOAD_DONE;
        }
    }

    /**
     * 实例化下拉刷新的箭头的动画效果
     * @param pAnimDuration 动画运行时长
     * @date 2013-11-20 上午11:53:22
     * @change JohnWatson
     * @version 1.0
     */
    private void initPullImageAnimation(final int pAnimDuration) {

        int _Duration;

        if(pAnimDuration > 0){
            _Duration = pAnimDuration;
        }else{
            _Duration = 250;
        }
//        Interpolator _Interpolator;
//        switch (pAnimType) {
//        case 0:
//            _Interpolator = new AccelerateDecelerateInterpolator();
//            break;
//        case 1:
//            _Interpolator = new AccelerateInterpolator();
//            break;
//        case 2:
//            _Interpolator = new AnticipateInterpolator();
//            break;
//        case 3:
//            _Interpolator = new AnticipateOvershootInterpolator();
//            break;
//        case 4:
//            _Interpolator = new BounceInterpolator();
//            break;
//        case 5:
//            _Interpolator = new CycleInterpolator(1f);
//            break;
//        case 6:
//            _Interpolator = new DecelerateInterpolator();
//            break;
//        case 7:
//            _Interpolator = new OvershootInterpolator();
//            break;
//        default:
//            _Interpolator = new LinearInterpolator();
//            break;
//        }

        Interpolator _Interpolator = new LinearInterpolator();

        mArrowAnim = new RotateAnimation(0, -180,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        mArrowAnim.setInterpolator(_Interpolator);
        mArrowAnim.setDuration(_Duration);
        mArrowAnim.setFillAfter(true);

        mArrowReverseAnim = new RotateAnimation(-180, 0,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        mArrowReverseAnim.setInterpolator(_Interpolator);
        mArrowReverseAnim.setDuration(_Duration);
        mArrowReverseAnim.setFillAfter(true);
    }

    /**
     * 测量HeadView宽高(注意:此方法仅适用于LinearLayout,请读者自己测试验证。)
     * @param pChild
     * @date 2013-11-20 下午4:12:07
     * @change JohnWatson
     * @version 1.0
     */
    private void measureView(View pChild) {
        ViewGroup.LayoutParams p = pChild.getLayoutParams();
        if (p == null) {
            p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_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);
        }
        pChild.measure(childWidthSpec, childHeightSpec);
    }

    /**
     *为了判断滑动到ListView底部没
     */
    @Override
    public void onScroll(AbsListView pView, int pFirstVisibleItem,
            int pVisibleItemCount, int pTotalItemCount) {
        mFirstItemIndex = pFirstVisibleItem;
        mLastItemIndex = pFirstVisibleItem + pVisibleItemCount - 2;
        mCount = pTotalItemCount - 2;
        if (pTotalItemCount > pVisibleItemCount ) {
            mEnoughCount = true;
//            endingView.setVisibility(View.VISIBLE);
        } else {
            mEnoughCount = false;
        }
    }

    /**
     *这个方法,可能有点乱,大家多读几遍就明白了。
     */
    @Override
    public void onScrollStateChanged(AbsListView pView, int pScrollState) {
        if(mCanLoadMore){// 存在加载更多功能
            if (mLastItemIndex ==  mCount && pScrollState == SCROLL_STATE_IDLE) {
                //SCROLL_STATE_IDLE=0,滑动停止
                if (mEndState != ENDINT_LOADING) {
                    if(mIsAutoLoadMore){// 自动加载更多,我们让FootView显示 “更    多”
                        if(mCanRefresh){
                            // 存在下拉刷新并且HeadView没有正在刷新时,FootView可以自动加载更多。
                            if(mHeadState != REFRESHING){
                                // FootView显示 : 更    多  ---> 加载中...
                                mEndState = ENDINT_LOADING;
                                onLoadMore();
                                changeEndViewByState();
                            }
                        }else{// 没有下拉刷新,我们直接进行加载更多。
                            // FootView显示 : 更    多  ---> 加载中...
                            mEndState = ENDINT_LOADING;
                            onLoadMore();
                            changeEndViewByState();
                        }
                    }else{// 不是自动加载更多,我们让FootView显示 “点击加载”
                        // FootView显示 : 点击加载  ---> 加载中...
                        mEndState = ENDINT_MANUAL_LOAD_DONE;
                        changeEndViewByState();
                    }
                }
            }
        }else if(mEndRootView != null && mEndRootView.getVisibility() == VISIBLE){
            // 突然关闭加载更多功能之后,我们要移除FootView。
            mEndRootView.setVisibility(View.GONE);
            this.removeFooterView(mEndRootView);
        }
    }

    /**
     * 改变加载更多状态
     * @date 2013-11-11 下午10:05:27
     * @change JohnWatson
     * @version 1.0
     */
    private void  changeEndViewByState() {
        if (mCanLoadMore) {
            //允许加载更多
            switch (mEndState) {
            case ENDINT_LOADING://刷新中

                // 加载中...
                if(mEndLoadTipsTextView.getText().equals(
                        R.string.p2refresh_doing_end_refresh)){
                    break;
                }
                mEndLoadTipsTextView.setText(R.string.p2refresh_doing_end_refresh);
                mEndLoadTipsTextView.setVisibility(View.VISIBLE);
                mEndLoadProgressBar.setVisibility(View.VISIBLE);
                break;
            case ENDINT_MANUAL_LOAD_DONE:// 手动刷新完成

                // 点击加载
                mEndLoadTipsTextView.setText(R.string.p2refresh_end_click_load_more);
                mEndLoadTipsTextView.setVisibility(View.VISIBLE);
                mEndLoadProgressBar.setVisibility(View.GONE);

                mEndRootView.setVisibility(View.VISIBLE);
                break;
            case ENDINT_AUTO_LOAD_DONE:// 自动刷新完成

                // 更    多
                mEndLoadTipsTextView.setText(R.string.p2refresh_end_load_more);
                mEndLoadTipsTextView.setVisibility(View.VISIBLE);
                mEndLoadProgressBar.setVisibility(View.GONE);

                mEndRootView.setVisibility(View.VISIBLE);
                break;
            default:
                // 原来的代码是为了: 当所有item的高度小于ListView本身的高度时,
                // 要隐藏掉FootView,大家自己去原作者的代码参考。

//                if (enoughCount) {
//                    endRootView.setVisibility(View.VISIBLE);
//                } else {
//                    endRootView.setVisibility(View.GONE);
//                }
                break;
            }
        }
    }

    /**
     *原作者的,我没改动,请读者自行优化。
     */
    public boolean onTouchEvent(MotionEvent event) {

        if (mCanRefresh) {
            if(mCanLoadMore && mEndState == ENDINT_LOADING){
                // 如果存在加载更多功能,并且当前正在加载更多,默认不允许下拉刷新,必须加载完毕后才能使用。
                return super.onTouchEvent(event);
            }

            switch (event.getAction()) {

            case MotionEvent.ACTION_DOWN:
                if (mFirstItemIndex == 0 && !mIsRecored) {
                    mIsRecored = true;
                    mStartY = (int) event.getY();
                }
                break;

            case MotionEvent.ACTION_UP:

                if (mHeadState != REFRESHING && mHeadState != LOADING) {
                    if (mHeadState == DONE) {

                    }
                    if (mHeadState == PULL_TO_REFRESH) {
                        mHeadState = DONE;
                        changeHeaderViewByState();
                    }
                    if (mHeadState == RELEASE_TO_REFRESH) {
                        mHeadState = REFRESHING;
                        changeHeaderViewByState();
                        onRefresh();
                    }
                }

                mIsRecored = false;
                mIsBack = false;

                break;

            case MotionEvent.ACTION_MOVE:
                int tempY = (int) event.getY();

                if (!mIsRecored && mFirstItemIndex == 0) {
                    mIsRecored = true;
                    mStartY = tempY;
                }

                if (mHeadState != REFRESHING && mIsRecored && mHeadState != LOADING) {

                    // 保证在设置padding的过程中,当前的位置一直是在head,
                    // 否则如果当列表超出屏幕的话,当在上推的时候,列表会同时进行滚动
                    // 可以松手去刷新了
                    if (mHeadState == RELEASE_TO_REFRESH) {

                        setSelection(0);

                        // 往上推了,推到了屏幕足够掩盖head的程度,但是还没有推到全部掩盖的地步
                        if (((tempY - mStartY) / RATIO < mHeadViewHeight)
                                && (tempY - mStartY) > 0) {
                            mHeadState = PULL_TO_REFRESH;
                            changeHeaderViewByState();
                        }
                        // 一下子推到顶了
                        else if (tempY - mStartY <= 0) {
                            mHeadState = DONE;
                            changeHeaderViewByState();
                        }
                        // 往下拉了,或者还没有上推到屏幕顶部掩盖head的地步
                    }
                    // 还没有到达显示松开刷新的时候,DONE或者是PULL_To_REFRESH状态
                    if (mHeadState == PULL_TO_REFRESH) {

                        setSelection(0);

                        // 下拉到可以进入RELEASE_TO_REFRESH的状态
                        if ((tempY - mStartY) / RATIO >= mHeadViewHeight) {
                            mHeadState = RELEASE_TO_REFRESH;
                            mIsBack = true;
                            changeHeaderViewByState();
                        } else if (tempY - mStartY <= 0) {
                            mHeadState = DONE;
                            changeHeaderViewByState();
                        }
                    }

                    if (mHeadState == DONE) {
                        if (tempY - mStartY > 0) {
                            mHeadState = PULL_TO_REFRESH;
                            changeHeaderViewByState();
                        }
                    }

                    if (mHeadState == PULL_TO_REFRESH) {
                        mHeadView.setPadding(0, -1 * mHeadViewHeight
                                + (tempY - mStartY) / RATIO, 0, 0);

                    }

                    if (mHeadState == RELEASE_TO_REFRESH) {
                        mHeadView.setPadding(0, (tempY - mStartY) / RATIO
                                - mHeadViewHeight, 0, 0);
                    }
                }
                break;
            }
        }

        return super.onTouchEvent(event);
    }

    /**
     * 当HeadView状态改变时候,调用该方法,以更新界面
     * @date 2013-11-20 下午4:29:44
     * @change JohnWatson
     * @version 1.0
     */
    private void changeHeaderViewByState() {
        switch (mHeadState) {
        case RELEASE_TO_REFRESH:
            mArrowImageView.setVisibility(View.VISIBLE);
            mProgressBar.setVisibility(View.GONE);
            mTipsTextView.setVisibility(View.VISIBLE);
            mLastUpdatedTextView.setVisibility(View.VISIBLE);

            mArrowImageView.clearAnimation();
            mArrowImageView.startAnimation(mArrowAnim);
            // 松开刷新
            mTipsTextView.setText(R.string.p2refresh_release_refresh);

            break;
        case PULL_TO_REFRESH:
            mProgressBar.setVisibility(View.GONE);
            mTipsTextView.setVisibility(View.VISIBLE);
            mLastUpdatedTextView.setVisibility(View.VISIBLE);
            mArrowImageView.clearAnimation();
            mArrowImageView.setVisibility(View.VISIBLE);
            // 是由RELEASE_To_REFRESH状态转变来的
            if (mIsBack) {
                mIsBack = false;
                mArrowImageView.clearAnimation();
                mArrowImageView.startAnimation(mArrowReverseAnim);
                // 下拉刷新
                mTipsTextView.setText(R.string.p2refresh_pull_to_refresh);
            } else {
                // 下拉刷新
                mTipsTextView.setText(R.string.p2refresh_pull_to_refresh);
            }
            break;

        case REFRESHING:
            mHeadView.setPadding(0, 0, 0, 0);

            // 华生的建议: 实际上这个的setPadding可以用动画来代替。我没有试,但是我见过。其实有的人也用Scroller可以实现这个效果,
            // 我没时间研究了,后期再扩展,这个工作交给小伙伴你们啦~ 如果改进了记得发到我邮箱噢~
            // 本人邮箱: [email protected]

            mProgressBar.setVisibility(View.VISIBLE);
            mArrowImageView.clearAnimation();
            mArrowImageView.setVisibility(View.GONE);
            // 正在刷新...
            mTipsTextView.setText(R.string.p2refresh_doing_head_refresh);
            mLastUpdatedTextView.setVisibility(View.VISIBLE);

            break;
        case DONE:
            mHeadView.setPadding(0, -1 * mHeadViewHeight, 0, 0);

            // 此处可以改进,同上所述。

            mProgressBar.setVisibility(View.GONE);
            mArrowImageView.clearAnimation();
            mArrowImageView.setImageResource(R.drawable.arrow);
            // 下拉刷新
            mTipsTextView.setText(R.string.p2refresh_pull_to_refresh);
            mLastUpdatedTextView.setVisibility(View.VISIBLE);

            break;
        }
    }

    /**
     * 下拉刷新监听接口
     * @date 2013-11-20 下午4:50:51
     * @change JohnWatson
     * @version 1.0
     */
    public interface OnRefreshListener {
        public void onRefresh();
    }

    /**
     * 加载更多监听接口
     * @date 2013-11-20 下午4:50:51
     * @change JohnWatson
     * @version 1.0
     */
    public interface OnLoadMoreListener {
        public void onLoadMore();
    }

    public void setOnRefreshListener(OnRefreshListener pRefreshListener) {
        if(pRefreshListener != null){
            mRefreshListener = pRefreshListener;
            mCanRefresh = true;
        }
    }

    public void setOnLoadListener(OnLoadMoreListener pLoadMoreListener) {
        if(pLoadMoreListener != null){
            mLoadMoreListener = pLoadMoreListener;
            mCanLoadMore = true;
            if(mCanLoadMore && getFooterViewsCount() == 0){
                addFooterView();
            }
        }
    }

    /**
     * 正在下拉刷新
     * @date 2013-11-20 下午4:45:47
     * @change JohnWatson
     * @version 1.0
     */
    private void onRefresh() {
        if (mRefreshListener != null) {
            mRefreshListener.onRefresh();
        }
    }

    /**
     * 下拉刷新完成
     * @date 2013-11-20 下午4:44:12
     * @change JohnWatson
     * @version 1.0
     */
    public void onRefreshComplete() {
        // 下拉刷新后是否显示第一条Item
        if(mIsMoveToFirstItemAfterRefresh)setSelection(0);

        mHeadState = DONE;
        // 最近更新: Time
        mLastUpdatedTextView.setText(
                getResources().getString(R.string.p2refresh_refresh_lasttime) +
                new SimpleDateFormat(DATE_FORMAT_STR, Locale.CHINA).format(new Date()));
        changeHeaderViewByState();
    }

    /**
     * 正在加载更多,FootView显示 : 加载中...
     * @date 2013-11-20 下午4:35:51
     * @change JohnWatson
     * @version 1.0
     */
    private void onLoadMore() {
        if (mLoadMoreListener != null) {
            // 加载中...
            mEndLoadTipsTextView.setText(R.string.p2refresh_doing_end_refresh);
            mEndLoadTipsTextView.setVisibility(View.VISIBLE);
            mEndLoadProgressBar.setVisibility(View.VISIBLE);

            mLoadMoreListener.onLoadMore();
        }
    }

    /**
     * 加载更多完成
     * @date 2013-11-11 下午10:21:38
     * @change JohnWatson
     * @version 1.0
     */
    public void onLoadMoreComplete() {
        if(mIsAutoLoadMore){
            mEndState = ENDINT_AUTO_LOAD_DONE;
        }else{
            mEndState = ENDINT_MANUAL_LOAD_DONE;
        }
        changeEndViewByState();
    }

    /**
     * 主要更新一下刷新时间啦!
     * @param adapter
     * @date 2013-11-20 下午5:35:51
     * @change JohnWatson
     * @version 1.0
     */
    public void setAdapter(BaseAdapter adapter) {
        // 最近更新: Time
        mLastUpdatedTextView.setText(
                getResources().getString(R.string.p2refresh_refresh_lasttime) +
                new SimpleDateFormat(DATE_FORMAT_STR, Locale.CHINA).format(new Date()));
        super.setAdapter(adapter);
    }

}

head.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- ListView的头部 -->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:layout_gravity="center_vertical">

    <!-- 内容 -->

    <RelativeLayout
        android:id="@+id/head_contentLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="8dp"
        android:paddingBottom="8dp">

        <!-- 箭头图像、进度条 -->

        <FrameLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:layout_marginLeft="30dp">

            <!-- 箭头 -->

            <ImageView
                android:id="@+id/head_arrowImageView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:contentDescription="@string/app_name"
                android:src="@drawable/arrow" />

            <!-- 进度条 -->

            <ProgressBar
                android:id="@+id/head_progressBar"
                style="?android:attr/progressBarStyleSmall"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:indeterminateDrawable="@drawable/progressbar_bg"
                android:visibility="gone" />
        </FrameLayout>

        <!-- 提示、最近更新 -->

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

            <!-- 提示 -->

            <TextView
                android:id="@+id/head_tipsTextView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/p2refresh_release_refresh"
                android:textColor="@color/pull_refresh_textview"
                android:textSize="18sp" />

            <!-- 最近更新 -->

            <TextView
                android:id="@+id/head_lastUpdatedTextView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="6dp"
                android:text="@string/p2refresh_refresh_lasttime"
                android:textColor="@color/gold"
                android:textSize="12sp" />
        </LinearLayout>
    </RelativeLayout>

</LinearLayout>

listfooter_more.xml

<?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:gravity="center"
    android:orientation="horizontal"
    android:padding="15dp"
    >

    <ProgressBar
        android:id="@+id/pull_to_refresh_progress"
        style="@android:style/Widget.ProgressBar.Small.Inverse"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:indeterminate="true"
        android:visibility="gone" >
    </ProgressBar>

    <TextView
        android:id="@+id/load_more"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10.0dp"
        android:gravity="center"
        android:text="@string/p2refresh_head_load_more"
        android:textColor="@color/black" >
    </TextView>

</LinearLayout>

colors.xml

   <color name="common_color_transparent">#00000000</color>
    <color name="pull_refresh_textview">#000000</color>
    <color name="gold">#000000</color>
    <color name="black">#000000</color>

string.xml

  <!-- 下拉刷新listView所需 -->
    <string name="p2refresh_release_refresh">松开刷新</string>
    <string name="p2refresh_pull_to_refresh">下拉刷新</string>
    <string name="p2refresh_doing_head_refresh">正在刷新…</string>
    <string name="p2refresh_doing_end_refresh">加载中…</string>
    <string name="p2refresh_refresh_lasttime">最近更新 : </string>
    <string name="p2refresh_head_load_more">加载更多</string>
    <string name="p2refresh_end_load_more">更    多</string>
    <string name="p2refresh_end_click_load_more">点击加载</string>

activity

lv.setOnLoadListener(new CustomListView.OnLoadMoreListener() {
            @Override
            public void onLoadMore() {
                请求数据
                lv.onLoadMoreComplete();
            }
        });

        lv.setOnRefreshListener(new CustomListView.OnRefreshListener() {
            @Override
            public void onRefresh() {
                请求数据
                lv.onRefreshComplete();
            }
        });

drawable/progressbar_bg.xml

<?xml version="1.0" encoding="utf-8"?>
<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toDegrees="360" >

    <shape
        android:innerRadiusRatio="3"
        android:shape="ring"
        android:thicknessRatio="8"
        android:useLevel="false" >
        <gradient
            android:centerColor="#FF7121"
            android:centerY="0.50"
            android:endColor="#FFFF00"
            android:startColor="#6BD3FF"
            android:type="sweep"
            android:useLevel="false" />
    </shape>

</animated-rotate>
时间: 2024-10-13 16:29:02

CustomListView的相关文章

Android ListView 下拉刷新 点击加载更多

最近项目中用到了ListView的下拉刷新的功能,总结了一下前辈们的代码,单独抽取出来写了一个demo作为示例. 效果图 下拉刷新: 加载更多: CustomListView.java [java] view plaincopy package com.example.uitest.view; import java.util.Date; import com.example.uitest.R; import android.content.Context; import android.uti

Android自定义View的三种实现方式

在毕设项目中多处用到自定义控件,一直打算总结一下自定义控件的实现方式,今天就来总结一下吧.在此之前学习了郭霖大神博客上面关于自定义View的几篇博文,感觉受益良多,本文中就参考了其中的一些内容. 总结来说,自定义控件的实现有三种方式,分别是:组合控件.自绘控件和继承控件.下面将分别对这三种方式进行介绍. (一)组合控件 组合控件,顾名思义就是将一些小的控件组合起来形成一个新的控件,这些小的控件多是系统自带的控件.比如很多应用中普遍使用的标题栏控件,其实用的就是组合控件,那么下面将通过实现一个简单

去除ListView 上下边界蓝色或黄色阴影

默认的情况下,在 ListView 滑动到顶部或者是底部的时候,会有黄色或者蓝色的阴影出现.在不同的版本号上解决办法是不同的,在 2.3 版本号之前能够在 ListView 的属性中通过设置 android:fadingEdge="none" 来解决这个问题,可是在 2.3 及以上版本号这中方法是无效的,这里,能够通过重写 ListView 用代码来设置模式,禁止其阴影的出现,以免影响美观.代码例如以下: package com.sunzn.cview; import android.

08_ListView使用2

实现带image的ListView. package com.example.listviewdemo; import android.app.Activity; import android.os.Bundle; import android.widget.ListView; public class CustomListView extends Activity{ private ListView lv; @Override protected void onCreate(Bundle sa

listview 回弹效果1

主要使用overScrollBy 方法,前提是必须填满整个屏幕才有效果 package com.weidingqiang.customlistview; import android.content.Context; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.widget.ListView; /** * Created by weidingqiang on 15/11/

android Fragment 实例 Listfragment listiew 下拉刷新 上拉加载 横向滑动事件监听

Android Fragment开发实例及他色功能说明 代码太长,请网盘下载附件源代码: http://yunpan.cn/cs24a2Z7C5kRk (提取码:a0cf)  有疑问的欢迎联系QQ972910164 一. CustomListView说明:可下拉刷新,上拉加载,横向滑动接口回调, /** * 功能类似ListView,天机以下特性: * 1. 可下拉刷新,上拉加载,实现CustomListView.OnPullListener接口 * 3. Slide切换,实现CustomLis

Android 编程下去除 ListView 上下边界蓝色或黄色阴影

默认的情况下,在 ListView 滑动到顶部或者是底部的时候,会有黄色或者蓝色的阴影出现.在不同的版本上解决的方法是不同的,在 2.3 版本之前可以在 ListView 的属性中通过设置 android:fadingEdge="none" 来解决问题,但是在 2.3 及以上版本这中方法是无效的,这里,可以通过重写 ListView 用代码来设置模式,禁止其阴影的出现,以免影响美观.代码如下: package com.sunzn.cview; import android.conten

SwipeRefreshLayout 官方下拉刷新组件

package com.weidingqiang.customlistview; import android.os.Handler; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.ArrayAdapter; import android.wid

9.解决ScrollView与ListView共存时ListView高度无法完全显示的问题。

问题: ScrollView与ListView共存时,ListView会只显示一行,其它行无法显示. 解决方案: 重写ListView如下即可解决问题. /**解决ScorllView与ListView共存时,ListView只显示一行.不能完全显示的问题. * @author Caiyuan Huang * 2014-9-26 */ public class CustomListView extends ListView { public CustomListView(Context cont