下拉刷新

这篇文章适合看了众多讲解下拉刷新、视图测量与绘制、事件分发仍然模糊不清的同学,android下拉刷新控件不知从何时起已经成为项目标配,所以熟悉下拉刷新控件变得尤为重要,本文将从下拉刷新控件入手,顺便学习下自定义控件和事件分发机制。
我们可以点进当下可拓展性最高、最流行的下拉刷新项目:android-Ultra-Pull-To-Refresh,发现里面有个核心类PtrFrameLayout,乍一看1368行,不管你晕不晕,反正我是晕的。好了,我们来个简易版的(Ps:引用NsRefreshLayout项目的代码来讲解,并且都只是伪代码或部分代码):

一、定义些可拓展的属性

像这样写在values/attrs.xml里(ps:其实你写在strings.xml里都没问题,xml的名字也可以自己取,只需要保证根标签是declare-styleaqle即可,而且这样分开写更方便查找):

<declare-styleable name="PtrFrameLayout">
     <attr name="ptr_pull_to_fresh" format="boolean" />
</declare-styleable>
二、获取到这些属性

确保在每三个构造函数里都可以拿到这些属性

public PtrFrameLayout(Context context) {
        this(context, null);
    }

    public PtrFrameLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public PtrFrameLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.PtrFrameLayout, 0, 0);
        mPullToRefresh = arr.getBoolean(R.styleable.PtrFrameLayout_ptr_pull_to_fresh, mPullToRefresh);
        arr.recycle();
    }
三、给布局添加头布局或底布局

在方法onFinishInflate()里以addView的形式添加自定义的头布局或者底布局,并使用第二部接收的值来填充属性(比如颜色,字体什么的)。

四、重写事件分发

目前主要有2种方式来重写事件分发。

  1. 重写onInterceptTouchEvent和onTouchEvent的方式
  • 重写onInterceptTouchEvent
public boolean onInterceptTouchEvent(MotionEvent ev) {
      case MotionEvent.ACTION_MOVE: {
               //判断是下拉刷新还是上拉加载更多
            if (disY > 0 && !canChildScrollUp() && mPullRefreshEnable) {
                        mCurrentAction = ACTION_PULL_DOWN_REFRESH;
                        return true;
            } else {
               return super.onInterceptTouchEvent(ev);
            }
}

对touch事件为MOVE类型的进行判断处理,如果满足拦截条件,进行拦截并返回true,如不满足条件或是类型不是MOVE的其他touch事件,执行super.onInterceptTouchEvent(ev),代表不拦截,由系统帮我们向下传递,遇到需要消费该事件的content(比如listview滑动)消费掉就完事了

  • 重写onTouchEvent

public boolean onTouchEvent(MotionEvent event){
case MotionEvent.ACTION_MOVE: {
handleScroll(dy);//处理头试图和内容视图的下滑
return true;//return super 或者false都没事
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
return releaseTouch();//处理释放操作,这里的返回值同上
}
}
```
原著在move那里返回的是true,其实无论返回什么都是可以的,因为已经重写了onInterceptTouchEvent,当遇到满足下拉刷新的情况自然会走自己的OnTouchEvent(),如果没有不满足条件,由于你是parentView,而且没有拦截事件,所以子布局优先消费,也跟你无关了,哈哈

  1. 重写dispatchTouchEvent的方式
    android-Ultra-Pull-To-Refresh就是用的这种方式,当满足刷新条件时return true表示自己处理了,如果没满足条件,执行super.dispatchTouchEventSupper(e)继续分发给孩子,个人觉得这种方式干预了系统的分发事件,毕竟孩子的所有触摸事件都是通过这个方法得来的,说没就没了,不像onInterceptTouchEvent拦截了还会丢给孩子一个cancel事件,所以这种系统级的事情就要我们自己去写了,不过瘾。。。
五、布局位移

上个部分有个伪代码handleScroll(),是用来位移孩子的方法,下面统计下位移视图的几种方式:

  1. layout()
  2. bringToFront()(需配合requestLayout使用)
  3. LayoutParams
  4. padding(设为负值就隐藏了)
  5. transactionY,transactionX
  6. offsetLeftAndRight() offsetTopAndBottom()
  7. Scroller
  8. scrollTo() scrollBy()
    以上8种其实可以分为2类,1234需要requestLayout(),所以当频繁调用时会卡,5678只是影响drawable部分,频繁调用也很顺滑。

总结

如果你想通过看完上面的内容,然后自己写一个完美的下拉刷新控件,我想还是需要很长时间的,毕竟里面还有很多的小细节没有涉及到,我只是帮大家把轮子分解得简单点,对轮子有一个大体的认知,小细节的地方不明白也不影响大局观嘛,毕竟写代码还是要有一个上帝视角,谁也不能一口吃个大胖子。

相关链接

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,837评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,551评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,417评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,448评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,524评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,554评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,569评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,316评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,766评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,077评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,240评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,912评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,560评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,176评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,425评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,114评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,114评论 2 352

推荐阅读更多精彩内容