android-Ultra-Pull-To-Refresh的一些使用

记录一下这个下拉刷新框架的使用,以后方便再看。

android-Ultra-Pull-To-Refresh是一个功能很强大的下拉刷新框架,比较流行的一个下拉刷新框架。

源码分析:

http://a.codekk.com/detail/Android/Grumoon/android-Ultra-Pull-To-efresh%20%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90

使用步骤:

1、定义xml文件,在里面加入PtrFrameLAyout,然后把需要刷新的视图作为子视图添加进去,子视图支持各种View,包括在内部进行横向滑动的ViewPager等。


2、然后可以在Java代码中setHeaderView或者直接在xml中再添加一个view作为刷新的头部视图。不设置头部view貌似不能下拉。

里面预定义了几个header可以使用,如MaterialHeader。

如果要自定义的话就可以参照里面的进行,只要用实现PtrUIHandler接口的View就行了。


3、然后进行各种设置

有6个参数可配置:
--阻尼系数
默认: 1.7f,越大,感觉下拉时越吃力。
--触发刷新时移动的位置比例
默认,1.2f,移动达到头部高度1.2倍时可触发刷新操作。
--回弹延时
默认 200ms,回弹到刷新高度所用时间
--头部回弹时间
默认1000ms
--刷新是保持头部
默认值 true.
--下拉刷新 / 释放刷新
默认为释放刷新

用xml或者Java设置都可以,如下

mPtrFrame.setResistance(1.7f);
mPtrFrame.setRatioOfHeaderHeightToRefresh(1.2f);
mPtrFrame.setDurationToClose(200);
mPtrFrame.setDurationToCloseHeader(1000);
// default is false
mPtrFrame.setPullToRefresh(false);
// default is true
mPtrFrame.setKeepHeaderWhenRefresh(true);


4.再就是处理刷新了。

通过PtrHandler,可以检查确定是否可以下来刷新以及在合适的时间刷新数据。

ptrFrame.setPtrHandler(new PtrHandler() {
    @Override
    public void onRefreshBegin(PtrFrameLayout frame) {
        frame.postDelayed(new Runnable() {
            @Override
            public void run() {
                ptrFrame.refreshComplete();
            }
        }, 1800);
    }

    @Override
    public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {
        // 默认实现,根据实际情况做改动
        return PtrDefaultHandler.checkContentCanBePulledDown(frame, content, header);
    }
});

注意这句,刷新完成之后要调用refreshComplete(),不然header不会隐藏起来。


5、其它注意的细节

  • ViewPager滑动冲突: disableWhenHorizontalMove()

  • 长按LongPressed, setInterceptEventWhileWorking()

  • 刷新时,保持内容不动,仅头部下移, setPinContent()

  • 设置自动刷新(默认开启的)autoRefresh(false/true)进行控制

  • 多指触碰时,会发生跳动,一个解决方法

@Override
    public boolean dispatchTouchEvent(MotionEvent e) {
        if (!isEnabled() || mContent == null || mHeaderView == null) {
            return dispatchTouchEventSupper(e);
        }
        dealMulTouchEvent(e);
        int action = e.getAction();
        switch (action) {
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                mPtrIndicator.onRelease();
                if (mPtrIndicator.hasLeftStartPosition()) {
                    if (DEBUG) {
                        PtrCLog.d(LOG_TAG, "call onRelease when user release");
                    }
                    onRelease(false);
                    if (mPtrIndicator.hasMovedAfterPressedDown()) {
                        sendCancelEvent();
                        return true;
                    }
                    return dispatchTouchEventSupper(e);
                } else {
                    return dispatchTouchEventSupper(e);
                }
            case MotionEvent.ACTION_DOWN:
                mHasSendCancelEvent = false;
                mPtrIndicator.onPressDown(e.getX(), e.getY());

                mScrollChecker.abortIfWorking();

                mPreventForHorizontal = false;
                // The cancel event will be sent once the position is moved.
                // So let the event pass to children.
                // fix #93, #102
                dispatchTouchEventSupper(e);
                return true;

            case MotionEvent.ACTION_MOVE:
                mLastMoveEvent = e;
                final int pointerIndex = MotionEventCompat.findPointerIndex(e, mActivePointerId);
                final float x = MotionEventCompat.getX(e, pointerIndex);
                final float y = MotionEventCompat.getY(e, pointerIndex);
                mPtrIndicator.onMove(x, y);
//                mPtrIndicator.onMove(e.getX(), e.getY());
                float offsetX = mPtrIndicator.getOffsetX();
                float offsetY = mPtrIndicator.getOffsetY();

                if (mDisableWhenHorizontalMove && !mPreventForHorizontal && (Math.abs(offsetX) > mPagingTouchSlop && Math.abs(offsetX) > Math.abs(offsetY))) {
                    if (mPtrIndicator.isInStartPosition()) {
                        mPreventForHorizontal = true;
                    }
                }
                if (mPreventForHorizontal) {
                    return dispatchTouchEventSupper(e);
                }

                boolean moveDown = offsetY > 0;
                boolean moveUp = !moveDown;
                boolean canMoveUp = mPtrIndicator.hasLeftStartPosition();

                if (DEBUG) {
                    boolean canMoveDown = mPtrHandler != null && mPtrHandler.checkCanDoRefresh(this, mContent, mHeaderView);
                    PtrCLog.v(LOG_TAG, "ACTION_MOVE: offsetY:%s, currentPos: %s, moveUp: %s, canMoveUp: %s, moveDown: %s: canMoveDown: %s", offsetY, mPtrIndicator.getCurrentPosY(), moveUp, canMoveUp, moveDown, canMoveDown);
                }

                // disable move when header not reach top
                if (moveDown && mPtrHandler != null && !mPtrHandler.checkCanDoRefresh(this, mContent, mHeaderView)) {
                    return dispatchTouchEventSupper(e);
                }

                if ((moveUp && canMoveUp) || moveDown) {
                    movePos(offsetY);
                    return true;
                }
        }
        return dispatchTouchEventSupper(e);
    }

    /**
     * http://blog.sina.com.cn/s/blog_8a86f4dd0102whbj.html
     * https://github.com/liaoinstan/SpringView/blob/master/library/src/main/java/com/liaoinstan/springview/widget/SpringView.java
     * 处理多点触控的情况,准确地计算Y坐标和移动距离dy
     * 同时兼容单点触控的情况
     */
    private int mActivePointerId = MotionEvent.INVALID_POINTER_ID;

    public void dealMulTouchEvent(MotionEvent ev) {
        final int action = MotionEventCompat.getActionMasked(ev);
        switch (action) {
            case MotionEvent.ACTION_DOWN: {
                final int pointerIndex = MotionEventCompat.getActionIndex(ev);
                final float x = MotionEventCompat.getX(ev, pointerIndex);
                final float y = MotionEventCompat.getY(ev, pointerIndex);
                mPtrIndicator.onPressDown(x, y);
                mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
                break;
            }
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                mActivePointerId = MotionEvent.INVALID_POINTER_ID;
                break;
            case MotionEvent.ACTION_POINTER_DOWN: {
                final int pointerIndex = MotionEventCompat.getActionIndex(ev);
                final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
                if (pointerId != mActivePointerId) {
                    final float x = MotionEventCompat.getX(ev, pointerIndex);
                    final float y = MotionEventCompat.getY(ev, pointerIndex);
                    mPtrIndicator.onPressDown(x, y);
                    mActivePointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
                }
                break;
            }
            case MotionEvent.ACTION_POINTER_UP: {
                PtrCLog.v(LOG_TAG, "ACTION_POINTER_UP: ");
                final int pointerIndex = MotionEventCompat.getActionIndex(ev);
                final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
                if (pointerId == mActivePointerId) {
                    final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
                    final float x = MotionEventCompat.getX(ev, pointerIndex);
                    final float y = MotionEventCompat.getY(ev, pointerIndex);
                    mPtrIndicator.onPressDown(x, y);
                    mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
                }
                break;
            }
        }
    }
目前只是简单的使用,以后遇到更多细节再添加了。



好的,下面是使用 van-pull-refresh 和 van-list 的示例代码: ```vue <template> <van-pull-refresh v-model="refreshing" @refresh="onRefresh"> <van-list :loading="loading" :finished="finished" :error="error" @load="onLoad"> <van-cell v-for="(item, index) in list" :key="index">{{ item }}</van-cell> </van-list> </van-pull-refresh> </template> <script> export default { data() { return { refreshing: false, loading: false, finished: false, error: false, list: [], page: 1, limit: 10 }; }, methods: { onRefresh() { this.refreshing = true; setTimeout(() => { this.page = 1; this.list = ['Item 1', 'Item 2', 'Item 3']; this.finished = false; this.refreshing = false; }, 1000); }, onLoad() { if (this.loading || this.finished) { return; } this.loading = true; setTimeout(() => { if (this.list.length >= 40) { this.finished = true; } else { this.page++; this.list.push(`Item ${this.page * this.limit - 8}`, `Item ${this.page * this.limit - 7}`, `Item ${this.page * this.limit - 6}`, `Item ${this.page * this.limit - 5}`, `Item ${this.page * this.limit - 4}`, `Item ${this.page * this.limit - 3}`, `Item ${this.page * this.limit - 2}`, `Item ${this.page * this.limit - 1}`, `Item ${this.page * this.limit}`); } this.loading = false; }, 1000); } } }; </script> ``` 在这个示例中,我们使用 van-pull-refresh 包裹 van-list,并且监听其 @refresh 事件来触发下拉刷新。同时,van-list 组件中的一些属性(如 loading、finished、error)和事件(如 @load)可以用于控制和监听列表的加载情况。在 onRefresh 和 onLoad 方法中,我们可以根据需要进行数据的请求和更新。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值