文档章节

PullToRefresh的学习研究(三)---子类们

j
 jscoolstar
发布于 2015/06/17 16:21
字数 2029
阅读 52
收藏 0

精选30+云产品,助力企业轻松上云!>>>

子类有多个,先从最常用最关注的说起吧。

1、public abstract class PullToRefreshAdapterViewBase<T extends AbsListView> extends PullToRefreshBase<T>

首先有这么一个成员变量:/**
     * TODO 提示器,比如滑动顶部的时候渐显出来,告诉用户这个位置可以下拉刷新了
     * @Auther : shenqichao
     * @Date:2015年6月17日 上午11:14:27
     */
    private IndicatorLayout mIndicatorIvTop;
    private IndicatorLayout mIndicatorIvBottom;

private OnScrollListener mOnScrollListener;这里定义了一个滑动监听,这其实是供给用户处理滑动事件的,它本身不处理刷新相关的逻辑,因为在构造里面有这么一句:public PullToRefreshAdapterViewBase(Context context) {
        super(context);
        mRefreshableView.setOnScrollListener(this);
    }

自己的refreshableView的滑动监听其实是子类自己,而在对应的各个接口函数里都会调用mOnScrollListener.do,比如:public final void onScrollStateChanged(final AbsListView view, final int state) {
        /**
         * Check that the scrolling has stopped, and that the last item is
         * visible.
         */
        if (state == OnScrollListener.SCROLL_STATE_IDLE && null != mOnLastItemVisibleListener && mLastItemVisible) {
            mOnLastItemVisibleListener.onLastItemVisible();
        }

        if (null != mOnScrollListener) {
            mOnScrollListener.onScrollStateChanged(view, state);
        }
    }

下面是子类核心功能作用,(指示器只是添花的作用,不要也不影响)

protected boolean isReadyForPullStart() {
        return isFirstItemVisible();
    }

    protected boolean isReadyForPullEnd() {
        return isLastItemVisible();
    }

先看第一个,是否准备好顶部下拉刷新了?return的是isFirstItemVisible();,虽然名字是这样起的,但是其方法内部并不是判断的仅仅是是否visiable。

private boolean isFirstItemVisible() {
        final Adapter adapter = mRefreshableView.getAdapter();

        if (null == adapter || adapter.isEmpty()) {
            if (DEBUG) {
                Log.d(LOG_TAG, "isFirstItemVisible. Empty View.");
            }
            return true;

        } else {

            /**
             * This check should really just be:
             * mRefreshableView.getFirstVisiblePosition() == 0, but PtRListView
             * internally use a HeaderView which messes the positions up. For
             * now we'll just add one to account for it and rely on the inner
             * condition which checks getTop().
             */
            if (mRefreshableView.getFirstVisiblePosition() <= 1) {
                final View firstVisibleChild = mRefreshableView.getChildAt(0);
                if (firstVisibleChild != null) {
                    return firstVisibleChild.getTop() >= mRefreshableView.getTop();
                }
            }
        }

        return false;
    }

代码解决了第一篇的一个疑问,即listview加了自己header之后是否还可用。这里可以看到代码是可用的。首先 if (mRefreshableView.getFirstVisiblePosition() <= 1) {感觉这里的代码有点累赘了,可能是sdk版本的问题?这里其实确实可以只用getFirstVisiblePosition()==0来判断的,在==0的时候,在获取getChildAt(0),去获取他的getTop和listview本身的gettop对比),写到这里的时候卡壳了,我研究了很久为什么作者要写成<=1,我自己做了个实验,用了个普通的listview,自己加了个header,有header的时候,就显示Header是0,没有就第一个元素是0,所以不管怎样我都觉得滑动要判断第0个,所以觉得作者不用写成<=1。但是我运行demo的代码,有header的时候getFirstVisiblePosition()=1,没header的时候也显示1,整的我特别的莫名其妙.由于马虎看了好久代码也没找到原因,后来~~~我终于明白了,什么是哎。。

PullToRefreshListView继承adpterview,

@Override
    protected void handleStyledAttributes(TypedArray a) {
        super.handleStyledAttributes(a);

        mListViewExtrasEnabled = a.getBoolean(R.styleable.PullToRefresh_ptrListViewExtrasEnabled, true);

        if (mListViewExtrasEnabled) {
            final FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
                    FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL);

            // Create Loading Views ready for use later
            FrameLayout frame = new FrameLayout(getContext());
            mHeaderLoadingView = createLoadingLayout(getContext(), Mode.PULL_FROM_START, a);
            mHeaderLoadingView.setVisibility(View.GONE);
            frame.addView(mHeaderLoadingView, lp);
            mRefreshableView.addHeaderView(frame, null, false);

            mLvFooterLoadingFrame = new FrameLayout(getContext());
            mFooterLoadingView = createLoadingLayout(getContext(), Mode.PULL_FROM_END, a);
            mFooterLoadingView.setVisibility(View.GONE);
            mLvFooterLoadingFrame.addView(mFooterLoadingView, lp);

            /**
             * If the value for Scrolling While Refreshing hasn't been
             * explicitly set via XML, enable Scrolling While Refreshing.
             */
            if (!a.hasValue(R.styleable.PullToRefresh_ptrScrollingWhileRefreshingEnabled)) {
                setScrollingWhileRefreshingEnabled(true);
            }
        }
    }这里是基类留给所有子类来处理自己的attr的, mListViewExtrasEnabled = a.getBoolean(R.styleable.PullToRefresh_ptrListViewExtrasEnabled, true);这行代码很长。。在写博客,并且要在模拟器上测试,所以eclipse不是最大化,这行代码没显示全,我理解的意思是listview是否可以扩展,即分组。所以认为取这属性时默认应该是false的。所以也就不会执行false里面的东西。。。但是我错了,小裤裤都错掉了。这个if里面加了mHeaderLoadingView,是真正意义上的加了。。。但是还设置成了visiable=gone,然后就出现了怪现象,第零个item总打印成他是第一个。然后我继续围绕代码和运行时的表现,发现mListViewExtrasEnabled这个字段不是代表分组的情况。而是当freshing的时候,listview是否可以滑动。当我实验完这个字段之后我又记起基类里有这个字段mScrollingWhileRefreshingEnabled,我就在想他们俩不是一个意思吗?然后又开始换状态运行发现了一个问题。mScrollingWhileRefreshingEnabled这个确实也是代表freshing的时候view是否可滑动。如果是false,那刷新的时候在基类的touch拦截那里就拦截了,所以也就无法滑动freshableview了。如果设置成true,就可以滑动,但是lsitview的体验是,他自己可以滑动,但是上面的head加载条却一直显示着,因为继承的LinearLayout,而且代码发现mScrollingWhileRefreshingEnabled这个是true的时候,在touch事件里面并没有处理scrollto来改变listview和header的滑动关系,比如代码处理的原理就是header位置不变,显示刷新中的状态,listview在“header”的下面可以上下滑动,说白了就是listview没有全屏,在下面的区域展示着自己。如果想做复杂点,我觉得应该在touch里面scrollto来改变header的位置,当达到临界值时,再不拦截touch,再交给freshableview去执行,这样就能实现listview和加载的header同时上移的视觉。mListViewExtrasEnabled这个属性,其实也是代表freshing的时候是否可以滑动。但是它作为一个单独出来的变量,仅仅是为了Listview自己的方便,这个属性默认为true,true的时候,会add一个真正的header,然后gone掉,当freshing的时候,他会把基类的headlayout隐藏掉,然后显示自己的header,并调用header的.freshing方法。当fresh完成,它再gone掉,然后显示基类的loadinglayout。。我觉得需要优化。抱着试试看的态度,我把gridview的demo设置成了刷新时可滑动属性,嗯,不好看。因为gridview不能加header。所以只能是第一种表现形式,而且发现一个UIbug:demo中是空的gridview,下拉刷行过程中,原来是不能滑动的,设置成可以滑动之后,因为gridview的是空的,lastvisiableitem自然是空的,所以你刚刚执行了下拉刷新后,马上往上提,底部会出现加载更多的footer,当然作者的代码逻辑只会让UI显示出来,却不会加载更多。但我觉得,加载更多也不该显示,同理,当加载更多的时候,也不应该下拉显示刷新的按钮,都应该等fresh结束之后,再去决定用户的操作是想下拉还是上拉。

好了,基本到这里了,listview竟然还是所有子类里面最复杂的一个。其他的几个都可以根据各自的特色来实现基类的abstract方法。比如webview,可以根据自己的contentheight属性(当然查了下api只有这个,没有contentwidth属性,也就意味着webview是不能左拉刷新的。。。)scollview就是根据getScrollY来判断。总之就是实现基类的@Override
    protected boolean isReadyForPullStart()
    protected boolean isReadyForPullEnd()

这两个方法,你甚至可以把方法内部写成滑动一半就刷新,只要你的子类告诉基类,我现在处于ready状态,基类再结合其他属性比如当前是“向上”还是“向下”滑动?等来决定现在要不要显示出LoadingLayout.

另外就是几个子类都根据api级别来构建listview/webview等等。因为api大于9的都有一个overScroll方法,通过OverScrollHelper来重新这个方法以达到更好的过量滑动视觉效果,如果api没有大于9,是无所谓了。


后记:listview里面有这样一句if (!a.hasValue(R.styleable.PullToRefresh_ptrScrollingWhileRefreshingEnabled)) {
                setScrollingWhileRefreshingEnabled(true);
            },当mListViewExtrasEnabled为true时,它会找xml配置,如果不存在那个属性配置就配置为true,这样mListViewExtrasEnabled才能生效,否则即使mListViewExtrasEnabled是true,如果xml明确配置ptrScrollingWhileRefreshingEnabled为false,那么也无法在freshing的时候滑动。看看能否优化成不使用mListViewExtrasEnabled,理论上所有的UI当下拉更新时,如果可以滑动,都应该带着顶部的loading一起滑动,不能因为只有listview有header所以有这样好的表现形式,而其他几个view就无法拥有这样的展现形式。


j
粉丝 0
博文 3
码字总数 6889
作品 0
海淀
程序员
私信 提问
加载中
请先登录后再评论。
框架源码系列五:学习源码的方法(学习源码的目的、 学习源码的方法、Eclipse里面查看源码的常用快捷键和方法)

一. 学习源码的目的   1. 为了扩展和调优:掌握框架的工作流程和原理   2. 为了提升自己的编程技能:学习他人的设计思想、编程技巧 二. 学习源码的方法 方法一:   1)掌握研究的对象和...

osc_y0xqgfqd
2019/03/17
4
0
C/C++ 学习手札(二)

我们研究一下继承和虚函数。 比如我们需要求正方形、长方形的周长、面积: 选择1计算长方形 选择2计算正方形 选择3退出 其他无效 我们做一个继承实现,父类矩形,子类有正方形、长方形继承矩...

五大三粗
2015/05/29
0
0
框架源码系列五:学习源码的方法(学习源码的目的、 学习源码的方法、Eclipse里面查看源码的常用快捷键和方法)

一. 学习源码的目的   1. 为了扩展和调优:掌握框架的工作流程和原理   2. 为了提升自己的编程技能:学习他人的设计思想、编程技巧 二. 学习源码的方法 方法一:   1)掌握研究的对象和...

小不点啊
2019/03/17
0
0
asp.net core mvc中自定义ActionResult

在GitHub上有个项目,本来是作为自己研究学习.net core的Demo,没想到很多同学在看,还给了很多星,所以觉得应该升成3.0,整理一下,写成博分享给学习.net core的同学们。 项目名称:Asp.Net...

桂素伟
2019/10/25
0
0
PullToRefresh的学习研究(一)

其实以前在看和学习源码的时候都是在源码上做关键的备注,后面看的时候能慢慢回忆起来,但是对比较复杂的逻辑,光靠备注还是不行,即使能回忆起来,也是十分耗费时间的。所以感觉还是要把学习...

jscoolstar
2015/06/16
126
0

没有更多内容

加载失败,请刷新页面

加载更多

要求jQuery在执行某些操作之前等待所有图像加载的官方方式

问题: In jQuery when you do this: 在jQuery中,当您执行以下操作时: $(function() { alert("DOM is loaded, but images not necessarily all loaded");}); It waits for the DOM t......

法国红酒甜
昨天
11
0
实现Map按值排序

Map按照值排序,需要自定义比较器,实现Comparator接口,实现compare方法。 public class SortByVlue {public static void main(String[] args) {Map<String, Long> map = new HashMap<......

游人未归
昨天
16
0
定天气爬虫加定时发送天气邮件

今天无聊,在家研究个爬虫玩玩 主要用到以下几个库: request 请求资源 iconv-lite转码,有的网站html格式不是utf-8 cheerio类似jq,操作html,获取相关爬虫数据 nodemailer 发送邮件,例如q...

莫西摩西
昨天
14
0
还在为大屏分辨率困扰?图扑提供响应式(自适应)可视化大屏

前言 数据可视化在当下信息时代已经成为炙手可热的话题,而 B/S 化趋势,也使得许多大屏应用上在网页端出现,今天给大家分享一套不一样风格的大屏页面,与传统深蓝色不同,这次采用了暗红色设...

xhload3d
昨天
20
0
如何妙用Spring 数据绑定机制

前言 在剖析完 Spring Boot 返回统一数据格式是怎样实现的?文章之后,一直觉得有必要说明一下 Spring's Data Binding Mechanism 「Spring 数据绑定机制」。 默认情况下,Spring 只知道如何转...

码农小胖哥
2019/12/27
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部