Android ListView 下拉刷新,上拉加载更多,带动画 自定义控件

之前每次 项目中用到ListView 的 下拉刷新 以及上拉分页加载 都是 用的 网上 下载 的 类库,

使用起来 诸多不便 ,于是 趁着有空 ,自己封装了ListView 让其 实现 下拉刷新,以及分页加载功能。

以下是 效果图:

当 滑动到 ListView 顶部 或 尾部 时,再次手指上拉或下拉 则会 触发 ListView 的 刷新 ,并 显示 刷新 动画,完成后动画会 缓慢消失。



Demo 下载 地址:点击打开链接

具体 实现原理:

首先对 ListView 要设置 OnScrollListener 监听 其 滑动 状态 ,并 记录此 状态。

ListView的 滑动 状态 有 三种

	静止状态,SCROLL_STATE_IDLE
	手指滚动状态,SCROLL_STATE_TOUCH_SCROLL
	手指不动了,但是屏幕还在滚动状态。SCROLL_STATE_FLING

上下拉刷新 时 ListView的 滚动状态 必须为 手指滚动才触发刷新。


还要 对 ListView 设置 触摸 监听。

判断 ListView 的 滑动 方向,计算其 手指拖动距离,以及手指抬起时的 刷新动画的 状态

以下是 ListView 的 触摸 和 滚动 监听 代码

首先 在 滚动 监听 了 记录 当前 的 滚动状态。

然后 在 触摸监听里  当状态 为 Action.Move 移动 时,判断滚动的 方向,以及 ListView 当前位置 处于顶部还是底部,并且 是否正在刷新。

然后 根据 手指 移动的 距离 除以相应倍数 ,让 刷新动画 控件 缓慢 出现。 在Action.Up 中 判断 当前的 刷新控件 显示 的 高度 是否 触发 刷新 方法。


    int currentScorllState;

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        currentScorllState = scrollState;
    }

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

    boolean rememberFreshYTag = true;
    float freshY;
    float tempY;
    int times = 3;
    boolean downTag = false;
    float y;

    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        y = motionEvent.getY();
        switch (motionEvent.getAction()) {
            case MotionEvent.ACTION_MOVE:
                float scrollHeight = y - tempY;
                if (scrollHeight > 0) {
                    downTag = true;
                } else {
                    downTag = false;
                }
                if (currentScorllState == OnScrollListener.SCROLL_STATE_TOUCH_SCROLL
                        && this.getFirstVisiblePosition() == 0
                        && this.getTop() == 0
                        && downTag
                        && !freshingTag
                        ) {
                    topFreshTag = true;
                    if (rememberFreshYTag) {
                        freshY = y;
                    }
                    rememberFreshYTag = false;

                    float min = Math.min(headHeight + headHeight / 2, (y - freshY) / times);
                    imageViewHead.setPadding(0, (int) (-headHeight + min), 0, 0);
                    Log.i("testss", "topFresh" + y);
                } else if (currentScorllState == OnScrollListener.SCROLL_STATE_TOUCH_SCROLL
                        && this.getLastVisiblePosition() == getCount() - 1
                        && this.getBottom() == this.getHeight()
                        && !downTag
                        && !freshingTag
                        ) {
                    bottomFreshTag = true;
                    if (rememberFreshYTag) {
                        freshY = y;
                    }
                    rememberFreshYTag = false;
                    float min = Math.min(footHeight + footHeight / 2, -(y - freshY));
                    imageViewFoot.setPadding(0, 0, 0, (int) (-footHeight + min));

                    Log.i("testss", "buttomFresh" + y + "---" + freshY);
                }
                break;
            case MotionEvent.ACTION_UP:
                if (topFreshTag && !freshingTag) {
                    Log.i("testss", "uptopFreshTag");
                    // 手指 抬起时 符合 条件 则 触发 顶部刷新
                    judgeToFresh(TOP_FRESH, imageViewHead, headHeight);
                }
                if (bottomFreshTag && !freshingTag) {
//                    Log.i("testss", "upbottomFreshTag");
                    // 手指 抬起时 符合 条件 则 触发 底部刷新
                    judgeToFresh(BOTTOM_FRESH, imageViewFoot, footHeight);
                }
                break;
        }
        tempY = y;
        return super.onTouchEvent(motionEvent);
    }



以下 是判断 是否 刷新的方法

 /**
     * 判断 是否 触发 刷新
     *
     * @param freshType 刷新 的类型 顶部刷新 或 底部刷新
     * @param imageView 刷新动画 的 控件
     * @param height    当前 刷新动画 控件 显示 的 高度
     */
    private void judgeToFresh(int freshType, ImageView imageView, int height) {

        int paddingHeight = freshType == TOP_FRESH ? imageView.getPaddingTop() : imageView.getPaddingBottom();
        if (paddingHeight == height / 2) {
            imageView.setPadding(0, 0, 0, 0);
            freshingTag = true;
            if (freshType == TOP_FRESH) {
                onTopFresh();
            } else {
                onBottomFresh();
            }
        } else {
            dissHeadOrFootView(imageView, freshType, -paddingHeight, height);
        }
    }

    /**
     * 开始 顶部 刷新
     */
    private void onTopFresh() {
        // 开启 动画
        startOrStopAnimation(imageViewHead, true);
        /**
         * 如果 设置 了外部 监听
         * 则 调用 外部监听 的 刷新 方法
         * 否则 过1s后 自动完成 刷新动画
         */
        if (onListViewFreshListener == null) {
            tempHandler.sendEmptyMessageDelayed(TOP_FRESH, 1000);
        } else {
            onListViewFreshListener.onTopFreshing();
        }
    }

    /**
     * 开始 底部 刷新
     */
    private void onBottomFresh() {
        // 开启 动画
        startOrStopAnimation(imageViewFoot, true);
        /**
         * 如果 设置 了外部 监听
         * 则 调用 外部监听 的 刷新 方法
         * 否则 过1s后 自动完成 刷新动画
         */
        if (onListViewFreshListener == null) {
            tempHandler.sendEmptyMessageDelayed(BOTTOM_FRESH, 1000);
        } else {
            onListViewFreshListener.onBottomFreshing();
        }
    }




Demo 下载 地址:点击打开链接


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值