自定义ListView控件实现下拉加载更多

通过自定义ListView控件实现下拉刷新功能。


public class RefreshListView extends ListView implements AbsListView.OnScrollListener {
    private View headerView;//初始化头布局
    private ProgressBar mProgressBar;//设置头布局的进度圈
    private TextView tvState;//设置头布局的状态
    private TextView tvLastUpdateTime;//设置头布局的最后刷新时间
    private int headerViewHeight;//记录头布局的高度
    private RotateAnimation upAnimation;
    private RotateAnimation downAnimation;
    private int downY;//按下时Y轴的偏移量
    private final int DOWN_PULL = 0;    // 头布局状态: 下拉刷新
    private final int RELEASE_REFRESH = 1;  // 头布局状态: 释放刷新
    private final int REFRESHING = 2;   // 头布局状态: 正在刷新中..
    private int currentState = DOWN_PULL; // 头布局当前的状态, 默认为: 下拉刷新
    private ImageView ivArrow; // 头布局的箭头

    private OnRefreshListener refreshListener;//define OnRefreshListener
    public RefreshListView(Context context) {
        super(context);
        initHeaderView();
        //设置手指滑动的监听器
        setOnScrollListener(this);
    }
    public RefreshListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initHeaderView();
    }

    /**
     * 初始化listview头布局
     */
    private void initHeaderView() {
        headerView=View.inflate(getContext(), R.layout.listview_header, null);
        //找到各个控件
         ivArrow = (ImageView) headerView.findViewById(R.id.iv_listview_header_arrow);
        mProgressBar = (ProgressBar) headerView.findViewById(R.id.pb_listview_header);
        tvState = (TextView) headerView.findViewById(R.id.tv_listview_header_state);
        tvLastUpdateTime = (TextView) headerView.findViewById(R.id.tv_listview_header_last_update_time);

        tvLastUpdateTime.setText("最后刷新时间: " + getCurrentTime());
        headerView.measure(0, 0);//都是0,说明让系统框架去测量头布局的  宽  高。
//        headerView.getHeight()//此方法是和headview没有显示到屏幕上之前而调用的,一直都是0
        headerViewHeight = headerView.getMeasuredHeight();//只有当measure方法被调用完毕后才可以得到具体高度
        //隐藏头布局
        headerView.setPadding(0,-headerViewHeight,0,0);
        //向listview的顶部追加一个布局
        this.addHeaderView(headerView);
        //添加箭头反转的动画
        initAnimation();

    }

    /**
     * 初始化动画
     */
    private void initAnimation() {
        upAnimation=new RotateAnimation(0,-180,
                Animation.RELATIVE_TO_SELF, 0.5f,
                Animation.RELATIVE_TO_SELF, 0.5f);
        upAnimation.setDuration(500);
        upAnimation.setFillAfter(true);//让控件停止在动画结束的状态

        downAnimation = new RotateAnimation(
                -180, -360,
                Animation.RELATIVE_TO_SELF, 0.5f,
                Animation.RELATIVE_TO_SELF, 0.5f);
        downAnimation.setDuration(500);
        downAnimation.setFillAfter(true); // 让控件停止在动画结束的状态下
    }

    /**
     *用于日期格式化的方法
     * @return
     */
    private String getCurrentTime() {
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
       return sdf.format(new Date());
    }


    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {

    }

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

    }

    /**
     * 手指滑动的事件
     * @param ev
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                downY= (int) ev.getY();

                break;
            case MotionEvent.ACTION_MOVE:
                int moveY= (int) ev.getY();
                //间距
                int diffY=moveY-downY;
                int paddingTop=-headerViewHeight+diffY;
                //获得第一个显示条目的索引
              int firstVisiblePosition =  getFirstVisiblePosition();
                if(paddingTop>-headerViewHeight&&firstVisiblePosition==0){
                    if(paddingTop > 0 && currentState == DOWN_PULL) { // 头布局完全显示, 并且当前状态是下拉刷新, 进入到松开刷新的状态
                        System.out.println("松开刷新");
                        currentState = RELEASE_REFRESH;
                        refreshHeaderViewState();
                    } else if(paddingTop < 0 && currentState == RELEASE_REFRESH) { // 头布局没有完全显示, 并且当前状态是松开刷新, 进入到下拉刷新的状态
                        System.out.println("下拉刷新");
                        currentState = DOWN_PULL;
                        refreshHeaderViewState();
                    }
                    headerView.setPadding(0,paddingTop,0,0);//让头布局显示的关键方法
//                    return true;//自己处理用户触摸的滑动的事件
                }
                break;
            case MotionEvent.ACTION_UP:
                // 判断当前的状态是哪一种
                if(currentState == DOWN_PULL) { // 当前是在下拉刷新状态下松开了, 什么都不做, 把头布局隐藏就可以.
                    headerView.setPadding(0, -headerViewHeight, 0, 0);
                } else if(currentState == RELEASE_REFRESH) { // 当前的状态属于释放刷新, 并且松开了. 应该把头布局正常显示, 进入正在刷新中状态.
                    headerView.setPadding(0, 0, 0, 0);
                    currentState = REFRESHING;
                    refreshHeaderViewState();
                    /**
                     * 调用用户的监听事件
                     */
                    if(refreshListener!=null){
                        refreshListener.onPullDownFresh();
                    }
                }


                break;
            default:

                break;
        }
        return super.onTouchEvent(ev);
    }

    /**
     * 刷新头布局的状态
     */
    private void refreshHeaderViewState() {
        switch (currentState) {
            case DOWN_PULL:  // 下拉刷新
                ivArrow.startAnimation(downAnimation);
                tvState.setText("下拉刷新");
                break;
            case RELEASE_REFRESH: // 松开刷新
                ivArrow.startAnimation(upAnimation);
                tvState.setText("松开刷新");
                break;
            case REFRESHING: // 正在刷新中
                ivArrow.clearAnimation(); // 把自己身上的动画清除掉
                ivArrow.setVisibility(View.INVISIBLE);
                mProgressBar.setVisibility(View.VISIBLE);
                tvState.setText("正在刷新..");
                break;
            default:
                break;
        }
    }
    /**
     * 刷新完成, 用户调用此方法, 把对应的头布局或脚布局给隐藏掉
     */
    public void onRefreshFinish() {

            // 隐藏头布局
            headerView.setPadding(0, -headerViewHeight, 0, 0);
            currentState = DOWN_PULL;
            mProgressBar.setVisibility(View.INVISIBLE);
            ivArrow.setVisibility(View.VISIBLE);
            tvState.setText("下拉刷新");
            tvLastUpdateTime.setText("最后刷新时间: " + getCurrentTime());

    }
    /**
     * 提供者给使用者设置刷新的监听事件
     * @param Listener
     */
    public void setRefreshListenere(OnRefreshListener Listener){
            refreshListener=Listener;
    }
    /**
     * 定义一个接口,当listview刷新时的监听事件,用户可以实现此方法,在listview正在刷新时
     */
    public interface OnRefreshListener{
        /**
         * 当下拉刷新时会掉此方法
         */
        public void onPullDownFresh();
    }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值