SuperSwipeRefreshLayout源码分析

SuperSwipeRefreshLayout源码分析

源码及DEMO

特性

  • 支持下拉刷新和上拉加载更多
  • 非侵入式,对原来的ListView、RecyclerView没有任何影响,用法和SwipeRefreshLayout类似。
  • 可自定义头部View的样式,调用setHeaderView方法即可
  • 可自定义页尾View的样式,调用setFooterView方法即可
  • 支持RecyclerView,ListView,ScrollView,GridView等等。
  • 被包含的View(RecyclerView,ListView etc.)可跟随手指的滑动而滑动
    默认是跟随手指的滑动而滑动,也可以设置为不跟随:setTargetScrollWithLayout(false)
  • 回调方法更多
    比如:onRefresh() onPullDistance(int distance)和onPullEnable(boolean enable)
    开发人员可以根据下拉过程中distance的值做一系列动画。

思路

自定义一个ViewGroup,往其中添加headerView和footerView,然后在onMeasure中确定它们的大小,在onLayout中确定它们的位置。当子View滑动到最上方的时候,或者最下方的时候,拦截事件,自己处理onTouchEvent事件;其他情况,交给子View自己处理onTouchEvent事件。
基于以上分析:需要重点关注的方法有:

  • addView
  • onMeasure
  • getChildDrawingOrder
  • onLayout
  • isChildScrollToTop
  • isChildScrollToBottom
  • onInterceptTouchEvent
  • onTouchEvent

addView

主要是添加headerView和footerView,这是第一步。

addView(mHeadViewContainer);
...
addView(mFooterViewContainer);

onMeasure

重写ViewGroup的onMeasure方法:
注意:onMeasure方法中只决定子View的大小,并不决定View的位置

@Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (mTarget == null) {
            ensureTarget();
        }
        if (mTarget == null) {
            return;
        }
        mTarget.measure(MeasureSpec.makeMeasureSpec(getMeasuredWidth()
                - getPaddingLeft() - getPaddingRight(), MeasureSpec.EXACTLY),
                MeasureSpec.makeMeasureSpec(getMeasuredHeight()
                        - getPaddingTop() - getPaddingBottom(),
                        MeasureSpec.EXACTLY));
        mHeadViewContainer.measure(MeasureSpec.makeMeasureSpec(
                mHeaderViewWidth, MeasureSpec.EXACTLY), MeasureSpec
                .makeMeasureSpec(mHeaderViewHeight, MeasureSpec.EXACTLY));
        mFooterViewContainer.measure(MeasureSpec.makeMeasureSpec(
                mFooterViewWidth, MeasureSpec.EXACTLY), MeasureSpec
                .makeMeasureSpec(mFooterViewHeight, MeasureSpec.EXACTLY));
        ...
        //查找在ViewGroup的index
        mHeaderViewIndex = -1;
        for (int index = 0; index < getChildCount(); index++) {
            if (getChildAt(index) == mHeadViewContainer) {
                mHeaderViewIndex = index;
                break;
            }
        }
        mFooterViewIndex = -1;
        for (int index = 0; index < getChildCount(); index++) {
            if (getChildAt(index) == mFooterViewContainer) {
                mFooterViewIndex = index;
                break;
            }
        }
    }

getChildDrawingOrder

重写ViewGroup的getChildDrawingOrder,由于HeaderView和FooterView刚开始是不显示的,分别隐藏在屏幕的上方和下方,因此,需要将它们两个的绘制顺序调整到最后。getChildDrawingOrder方法的含义是第i次应该绘制哪一个childView

    /**
     * 孩子节点绘制的顺序
     * 
     * @param childCount
     * @param i
     * @return
     */
    @Override
    protected int getChildDrawingOrder(int childCount, int i) {
       
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值