Ultra-Pull-To-Refresh的一些问题

Ultra-Pull-To-Refresh的一些问题

阿里廖祜秋的android-Ultra-Pull-To-Refresh是个非常好的库. 虽然有些许bug,但是掩盖不了它的精彩.
https://github.com/liaohuqiu/android-Ultra-Pull-To-Refresh

解决android-Ultra-Pull-To-Refresh下拉刷新组件中嵌套ViewPager的一个bug issues#133

UPTR和ViewPager一起使用是, 滑动事件会有一些冲突.这个issues里面提供了几个方法.

将

public boolean dispatchTouchEvent(MotionEvent e) {

}
move事件中的

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

if (mDisableWhenHorizontalMove && (Math.abs(offsetX) > mPagingTouchSlop && Math.abs(offsetX) > Math.abs(offsetY * mPtrIndicator.getResistance()))) {
    return dispatchTouchEventSupper(e);
}
然后将
mPagingTouchSlop = conf.getScaledTouchSlop() * 2, 
改为 
mPagingTouchSlop = conf.getScaledTouchSlop();

因为在横向滑动的过程中,可能会触发下拉导致mPtrIndicator.isInStartPosition()这个条件不成立,导致不会调用supper方法。
offsetY在PtrIndicator做了offsetY = offsetY/mResistance 处理。(这个不影响,不过我觉得还是应该改成offsetY * mPtrIndicator.getResistance())
让横向滑动的mPagingTouchSlop小一点可以让横滑容易一点。
感谢 @liaohuqiu 提供这么伟大的库,我从中学到了很多。

评价: 我试了你的方案,发现viewpager在move的过程中只要稍稍有垂直方向的移动便会回到原来的位置,实际效果就是很难翻页。

  • 方法三: (这个是解释原因的)
if (mDisableWhenHorizontalMove && !mPreventForHorizontal && (Math.abs(offsetX) > mPagingTouchSlop && Math.abs(offsetX) > Math.abs(offsetY))) {
    if (mPtrIndicator.isInStartPosition()) {
        mPreventForHorizontal = true;
    }
}
在以上代码中,作者的offsetX是touchevent与上一次 touchevent的差。错误在于作者将mPagingTouchSlop与offsetX做比较。因为offsetX实质是ΔX,不是距离。正确的比较方案应该是mPagingTouchSlop与(当前touchevent-按下时touchevent)做比较,进而给mPreventForHorizontal赋值
  • 方法四:
我找到了一个解决这个问题的好方法,代码如下:

mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
    @Override
    public void onPageScrollStateChanged(int state) {
        mPtrFrame.setEnabled(state == ViewPager.SCROLL_STATE_IDLE);
    }
});
我使用这段代码,效果挺好的。只要是滑动ViewPager时便不会将下拉刷新滑动出来了。这种方法同样也适用于官方的SwipeRefreshLayout和ViewPager配合。

我测试了这个项目和官方的下拉刷新控件,都能完美解决问题。我相信这段代码同样适用于你们的问题。

评价: 我使用的是该方案. 效果不错. 感谢.

  • 方法五:
目前我通过修改PtrFramLayout源码解决了这个问题,目前的几种使用场景如下:
1. ViewPager放在PtrFramLayout的顶部。
2. PtrFramLayout中嵌套ScrollView,ScrollView中放一个ViewGroup,ViewGroup的顶部放ViewPager。
3. ViewPager中嵌套PtrFramLayout,好吧其实前三种就是PtrFramLayout和ViewPager相互嵌套啦。
4. ViewPager放在Layout的非顶部。

其中第三种滑动没有问题,没有冲突,主要就是第一种和第二种。需要修改的代码仅仅一行:

if (mDisableWhenHorizontalMove && !mPreventForHorizontal && (Math.abs(offsetX) > mPagingTouchSlop && Math.abs(offsetX) > Math.abs(offsetY))) {
    if (mPtrIndicator.isInStartPosition()) {
        mPreventForHorizontal = true;
    }
}
把上述代码的if判断的Math.abs(offsetX) > mPagingTouchSlop这一句去掉就可以了,完整代码如下:

if (mDisableWhenHorizontalMove && !mPreventForHorizontal && Math.abs(offsetX) > Math.abs(offsetY)) {
    if (mPtrIndicator.isInStartPosition()) {
        mPreventForHorizontal = true;
    }
}
原因是,我们既然要禁用横向滑动的拦截,那么判断操作为横向并且要禁用横向拦截时给mPreventForHorizontal赋值为true即可,并不需要判断滑动距离。
同时PtrFramLayout的第113114行代码就无用了,可以注释了,第54行mPagingTouchSlop成员变量也无用,可以注释了。
使用的同学请注意还是需要调用PtrFrameLayout.disableWhenHorizontalMove(true)来灵活控制是否需要拦截。

评价: 达哥的解决方案. 横向滑动的问题解决了. 但是下拉刷新必须要非常垂直才能拉出.
博文在此: http://blog.csdn.net/yanzhenjie1003/article/details/51319181

android-Ultra-Pull-To-Refresh嵌套上下滑动View时滑动冲突 [这里的解决方案来自达哥的博文]

http://blog.csdn.net/yanzhenjie1003/article/details/51319181

其实PtrFramLayout的刷新接口PtrHandler提供了一个方法checkCanDoRefresh(…)来检查是否允许刷新,我们只需要在这里做判断返回true和false就OK了。
  然而我们的作者liaohuqiu同学也是想的非常周到,提供了一个PtrDefaultHandler类,实现了和SwipeRefreshLayout同样的判断,so看到这里的同学肯定知道怎么改了吧,我们先来看看PtrDefaultHandler源码:

public abstract class PtrDefaultHandler implements PtrHandler {

    public static boolean canChildScrollUp(View view) {
        if (android.os.Build.VERSION.SDK_INT < 14) {
            if (view instanceof AbsListView) {
                final AbsListView absListView = (AbsListView) view;
                return absListView.getChildCount() > 0
                        && (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)
                        .getTop() < absListView.getPaddingTop());
            } else {
                return view.getScrollY() > 0;
            }
        } else {
            return view.canScrollVertically(-1);
        }
    }

    /**
     * Default implement for check can perform pull to refresh
     *
     * @param frame
     * @param content
     * @param header
     * @return
     */
    public static boolean checkContentCanBePulledDown(PtrFrameLayout frame, View content, View header) {
        return !canChildScrollUp(content);
    }

    @Override
    public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {
        return checkContentCanBePulledDown(frame, content, header);
    }
}

所以我们在使用刷新接口的时候使用PtrDefaultHandler就好了,重写checkCanDoRefresh()方法:

private ScrollView scrollView;

...

private PtrDefaultHandler defaultHandler = new PtrDefaultHandler() {

    @Override
    public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {
        return !canChildScrollUp(scrollView);
    }

    @Override
    public void onRefreshBegin(PtrFrameLayout frame) {
        // 做刷新的操作
        ...
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值