自定义Listview分析:
GetListview/findViewById时调用的(用户第一个调用的方法):
1,首先3个构造方法都是在getlistview之findViewById()的时候调用的,用于初始化一些关于listview的一些参数。(其实findviewbyid就是new一个标签指定类型的对象,并且把标签中指定的属性作为一个set集合传过去,然后返回该标签类型对象,仅此而已)
2,Init(context) 初始化两个动画,一个inflateer 一个mRefreshView和它内部的四个控件。其次给它的mRrefreshView(header)绑定了一个点击事件监听器,OnClickRefreshListener,
该监听器监听点击动作(动作产生时:调用(如果mRefreshState为RefreshIng)PrepareForRefresh()和OnRefresh();其中具体的细节稍后再谈。),还有super.setOnScrollListerner()为该控件绑定滚动监听;
其中还包括了对mRefreshView的测量,测量过程不太懂。。。。
用户调用的第二个方法setOnRefreshListener();
1,在用户通过getListview或许findviewById以后紧接着就会给该自定义控件绑定一个OnRefreshListener(当然是自定义的),以便监听刷新事件的触发,开启异步任务。
2,具体的细节如下:
setOnRefreshLisner()以后,PullToRefreshListview会把OnRefreshListener保存到本地变量mOnRefreshListener中,等待刷新事件触发,就调用mOnRefreshListener中的OnRefresh()开启异步任务。
用户调用的最后一个方法onRefreshComplete(String)
1当时数据更新完毕的时候调用的方法,通知控件数据更新完毕,控件进行合理的显示调整。
2,具体地,当调用上述方法并传入一个字符串类型数据以后,会调用两个方法
setlastUpdated(用户传入的字符串);
onRefreshComeplete();
下面按照调用顺序介绍pullToRefreshListView控件中定义的各个方法;
1,三个构造方法在获得该类对应控件的时候调用的,不在多说
2,Init()在构造方法里调用,上面已经说过
3,OnAttachedToWindow()在onDraw()之前调用,此处是为了将listview默认显示第二个(setSelection(1));
4,setAdaper()设置适配器以后时会调用的方法,此处同样是为了将listview默认显示第二条。
5,onTouchEvent()当用户Touch到该控件的时候就会调用的方法:
此处,首先取得点击的y坐标,设置mBounceHack为false。
其次,对事件进行匹配,
如果是Action_up,就让滚动条可见,
如果,header可见并且状态不是正在刷新,分两种情况,
A;如果mRefreshView被全部拉出,而且现在的状态是RELEASE_TO_REFRESH那么就把状态改为 REFRESHING
然后调用prepareForRefresh();//做刷新时视图应该做的改变
onRefresh();//开启异步任务
B:如果mRefreshView只被拉出了一部分,就调用:
resetHeader();
setSelection(1);
如果是Action_Down: 记录 y坐标到mLastMotionY = y;
如果是ACTION_MOVE
applyHeaderPadding(event);
6,下面就分析一下applyHeaderPadding(MotionEvent ev)
根据ev事件中包含的滑动信息,得出应该有的padding,并setPading到mRefreshView上。(类似的resetHeaderPadding()是指把padding归零)
(resetHeader()表示吧header弄到原始状态。)
7,最后就是onScroll 和onscrollstateChagede()
前者滚动状态和mRefreshView的高度判断如何动作,后者只是在state为
SCROLL_STATE_IDLE的时候吧mBounceHack置为false。也就是说,mBounceHack仅仅表示飞速滑动状态下的状态,至于为什么要用这个变量我也不清楚。
至此整个流程已经基本明了了,当初始化该PullToRefreshListView控件以后,通过setOnRefreshListener()监听该控件的“Refresh”事件。
当用户滚动该控件的时候总是先触发,其中的onTouchEvent()事件,在该事件当中,会判断该listview应该有的状态, 然后当onScroll事件触发的时候,进行相关的控件显示动作,当用户拉到控件高度的时候触发异步任务,最后提示,加载完成,更新控件的显示。
其中关于老师认为很巧妙的两个ScrollListener:
1首先要明白onscrollListener是在用户滚动了布局中的控件,控件滚动了以后会触发的事件,至于listview的滚动式无需我们操心的,我们只需要关系滚动的时候我们应该做什么酒行了。
2至于本pullToRefreshListView来说对外曝光了SetOnScrooListener()
同时他父类也有setOnScrollListener();所以如果该控件不复写这个setOnscrollListener()
当我们用这个类的实例调用该方法的时候就会调用父类的setonstrolllister()方法。吧onscrollListener设置到系统类中的monScrollListener;
这样当用户触发absListView的滚动事件的时候就会调用刚刚定义的onstrolllistener中的方法
但是我们不但要对外曝光setOnscrollLisner()供使用该类实例的程序员监听滚动事件,
同时我们在定义这个类的时候也需要监听该滚动事件,因为我们不是系统,我们写的代码也是被调用的。
于是矛盾就来了,系统只会有一个mOnscrollListener实例,我们却又两处要对其进行监听
怎么解决呢?
它给出了这样一个解决方案。
即:复写setOnscrollListener 这样在程序员使用这个PulltoRefreshListView,并监听其滚动事件的时候,调用的setOnscrollLisner 就不在是父类中的setonscrollListener了而是复写过的,
这样在复写中的方法里吧传入的onScrollListenrer保存到本类中的monScrollListener,
在本类对象监听到滚动事件的时候处理完自己的逻辑以后再调用mscrollLisner中相应的方法即可
这就是多处同时监听一个事件的方法。