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

尉迟招
2023-12-01

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

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;
            }
        }
    }
目前只是简单的使用,以后遇到更多细节再添加了。



 类似资料: