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

来源:互联网 发布:西安事变 知乎 编辑:程序博客网 时间:2024/05/17 04:42

之前每次 项目中用到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 下载 地址:点击打开链接


0 0
原创粉丝点击