美文网首页andnroidTECH_ANDROID
android-Ultra-Pull-To-Refresh下拉刷

android-Ultra-Pull-To-Refresh下拉刷

作者: L_Xian | 来源:发表于2016-06-27 11:57 被阅读6781次

    大家都知道android-Ultra-Pull-To-Refresh是一个功能很强大的下拉刷新框架。

    项目地址:https://github.com/liaohuqiu/android-Ultra-Pull-To-Refresh

    原理剖析文档:android-Ultra-Pull-to-Refresh

    Demo地址:https://raw.githubusercontent.com/liaohuqiu/android-Ultra-Pull-To-Refresh/master/ptr-demo.apk

    相信正常的使用都没什么问题,但是有些点还是要注意的。

    1、自定义下拉头部的几个方法的调用时机:

    /**
    * 重置 View ,隐藏忙碌进度条,隐藏箭头 View ,更新最后刷新时间。
    * Content 重新回到顶部, Header 消失,整个下拉刷新过程完全结束以后,重置 View 。
    */
    @Override
    public void onUIReset(PtrFrameLayout ptrFrameLayout) {
    }
    
    /**
     * 准备刷新,隐藏忙碌进度条,显示箭头 View ,显示文字,如果是下拉刷新,显示“下拉刷新”,如果是释放刷新,显示“下拉”。
     * 准备刷新,Header 将要出现时调用。
     */
    @Override
    public void onUIRefreshPrepare(PtrFrameLayout ptrFrameLayout) {
    }
    
    /**
     * 开始刷新,Header 进入刷新状态之前调用。
     * 开始刷新,隐藏箭头 View ,显示忙碌进度条,显示文字,显示“加载中...”,更新最后刷新时间。
     */
    @Override
    public void onUIRefreshBegin(PtrFrameLayout ptrFrameLayout) {
    }
    
    /**
     * 刷新结束,隐藏箭头 View ,隐藏忙碌进度条,显示文字,显示“更新完成”,写入最后刷新时间。
     * 刷新结束,Header 开始向上移动之前调用。
     */
    @Override
    public void onUIRefreshComplete(PtrFrameLayout ptrFrameLayout) {
    }
    
    /**
     * 下拉过程中位置变化回调。
     * <p>
     * 在拖动情况下,当下拉距离从 小于刷新高度到大于刷新高度 时,箭头 View 从向下,变成向上,同时改变文字显示。
     * 当下拉距离从 大于刷新高度到小于刷新高度 时,箭头 View 从向上,变为向下,同时改变文字显示。
     */
    @Override
    public void onUIPositionChange(PtrFrameLayout ptrFrameLayout, boolean b, byte b1, PtrIndicator ptrIndicator) {
       float percent = Math.min(1f, ptrIndicator.getCurrentPercent());
    }
    

    然后在自定义头部的时候最好把布局也顺便写进去,这样使用起来就比较方便一点:

    public class CommonPtrHeader extends FrameLayout implements PtrUIHandler{
        private View headerView;
        private ProgressBar mProgressBar;
    
        public CommonPtrHeader(Context context) {
            super(context);
            init();
        }
    
        public CommonPtrHeader(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        private void init() {
            headerView = LayoutInflater.from(getContext()).inflate(R.layout.pull_to_refresh_head, this);
            mProgressBar = (ProgressBar) headerView.findViewById(R.id.pull_to_refresh_progress);
        }
    }
    

    2、当下拉刷新中有 ViewPager 时,比如 ListView 上面加个 Banner 广告条,这时候其实是会有滑动冲突的,那么网上搜很多都说要重写 ViewPager 或者 PtrFrameLayout,而且大部分都是达不到效果的,其实细心的你可能会发现,PtrFrameLayout 已经提供好方法来解决这一问题了,只是我们平时比较容易忽略:

    Q&A

    好了,只需要这样就能解决冲突了:

    ptrFrame.disableWhenHorizontalMove(true);
    

    -----------------------------分割线(补充)-------------------------------------------------------

    上面说的设置 disableWhenHorizontalMove ,大家是不是发现好像没什么用,是的,下面在网上找了个方法,使用中顺利解决了冲突问题,而且好像还没发现什么问题,需要重写一下 PtrClassicFrameLayout ,下面是代码:

    public class FixPtrFrameLayout extends PtrClassicFrameLayout {
    
        private float startY;
        private float startX;
        // 记录viewPager是否拖拽的标记
        private boolean mIsHorizontalMove;
        // 记录事件是否已被分发
        private boolean isDeal;
        private ViewPager mViewPager;
        private int mTouchSlop;
    
        public FixPtrFrameLayout(Context context) {
            super(context);
        }
    
        public FixPtrFrameLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public FixPtrFrameLayout(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
        /**
         * PtrHTFrameLayout has a viewpager
         *
         * @param viewPager
         */
        public void setViewPager(ViewPager viewPager) {
            this.mViewPager = viewPager;
            if (mViewPager == null) {
                throw new IllegalArgumentException("viewPager can not be null");
            }
            final ViewConfiguration configuration = ViewConfiguration.get(getContext());
            mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration);
        }
    
        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            if (mViewPager == null) {
                return super.dispatchTouchEvent(ev);
            }
            int action = ev.getAction();
            switch (action) {
                case MotionEvent.ACTION_DOWN:
                    // 记录手指按下的位置
                    startY = ev.getY();
                    startX = ev.getX();
                    // 初始化标记
                    mIsHorizontalMove = false;
                    isDeal = false;
                    break;
                case MotionEvent.ACTION_MOVE:
                    // 如果已经判断出是否由横向还是纵向处理,则跳出
                    if (isDeal) {
                        break;
                    }
                    /**拦截禁止交给Ptr的 dispatchTouchEvent处理**/
                    mIsHorizontalMove = true;
                    // 获取当前手指位置
                    float endY = ev.getY();
                    float endX = ev.getX();
                    float distanceX = Math.abs(endX - startX);
                    float distanceY = Math.abs(endY - startY);
                    if (distanceX != distanceY) {
                        // 如果X轴位移大于Y轴位移,那么将事件交给viewPager处理。
                        if (distanceX > mTouchSlop && distanceX > distanceY) {
                            mIsHorizontalMove = true;
                            isDeal = true;
                        } else if (distanceY > mTouchSlop) {
                            mIsHorizontalMove = false;
                            isDeal = true;
                        }
                    }
                    break;
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                    //下拉刷新状态时如果滚动了viewpager 此时mIsHorizontalMove为true 会导致PtrFrameLayout无法恢复原位
                    // 初始化标记,
                    mIsHorizontalMove = false;
                    isDeal = false;
                    break;
            }
            if (mIsHorizontalMove) {
                return dispatchTouchEventSupper(ev);
            }
            return super.dispatchTouchEvent(ev);
        }
    }
    

    使用方法就是通过里面的 setViewPager 方法将你的 banner里面的 viewpager 赋值进去就好,如果你的 banne r是写在 adapter 里面的,那你可以将 FixPtrFrameLayout 的实例赋值进去 adapter 里面,再设置 viewpager 就行。

    相关文章

      网友评论

        本文标题:android-Ultra-Pull-To-Refresh下拉刷

        本文链接:https://www.haomeiwen.com/subject/vlqndttx.html