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

来源:互联网 发布:中科大软件学院老师 编辑:程序博客网 时间:2024/06/06 04:58

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里面提供了几个方法.

  • 方法一:

    http://dengyin2000.iteye.com/blog/2232210
    评价: 按照你的博客来,还是没能解决问题。ViewPager可正常滑动,但是此时下拉刷新却很容易出不来。

  • 方法二:

将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