首先PullToRefreshView是一个上拉刷新下拉加载的一个自定义组件,它支持三种view,ListView,GridView和ScrollView的刷新操作,这里就针对其中自己觉得比较有用的一部分进行分析。代码会放在下面。在下有的地方也不是很懂,如果有不对的地方请指正。先给个图找找感觉。
转载请注明出处:http://blog.csdn.net/baozhuifeng/article/details/9835549
在TestListView.java里面有这样一段代码,这里TestListView这个类继承了ListActivity并且实现了在PullToRefreshView类中的OnHeaderRefreshListener,OnFooterRefreshListener监听接口,下面就是重写了OnHeaderRefreshListener中的onHeaderRefresh方法,并用View.PostDelayed(Runnabe,long)在1秒后启动后台线程在UI上进行上拉刷新的view的更改。这一步看起来简单,但是背后是
加载PullToRefreshView组件以及触摸屏幕发生一些操作,其中涉及两个refreshview的加载及变化操作,触摸手势判断监听,动画以及平滑拉动等操作,下面自己觉得重要不好懂的地方的分析下。
@Override
public void onHeaderRefresh(PullToRefreshView view) {
mPullToRefreshView.postDelayed(new Runnable() {
@Override
public void run() {
//设置更新时间
//mPullToRefreshView.onHeaderRefreshComplete("最近更新:01-23 12:01");
mPullToRefreshView.onHeaderRefreshComplete();
}
},1000);
}
首先来看下这个最关键的自定义组件类PullToRefreshView,它继承了LinearLayout这个ViewGroup子类,为什么要继承这个类呢,首先我们去掉中间那些列表,一头一尾剩下两个refreshView被一个ViewGroup给包裹起来,这就是可以进行复用的部分了,以后不管是那个app需要这个刷新组件,用PullToRefreshView去代替LinearLayout这样的布局组件就行了,然后实现onHeaderRefresh和onFooterRefresh就行了。
PullToRefreshView这个组件大概有600行代码,前面是一堆要定义这个组件的其他组件和参数的申明定义。接下来在构造器中进行初始化,构造器中调用了一个init方法。
private void init() {
// Load all of the animations we need in code rather than through XML
mFlipAnimation = new RotateAnimation(0, -180,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
mFlipAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
mFlipAnimation.setDuration(250);
mFlipAnimation.setFillAfter(true);
mReverseFlipAnimation = new RotateAnimation(-180, 0,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
mReverseFlipAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
mReverseFlipAnimation.setDuration(100);
mReverseFlipAnimation.setFillAfter(true);
mInflater = LayoutInflater.from(getContext());
// header view 在此添加,保证是第一个添加到linearlayout的最上端
addHeaderView();
}
这里关键部分就是旋转动画RotateAnimation类,我们看见的那个下拉时会动的箭头就是这个地方的作用,在你进行下拉操作时那个箭头的ImageView以动画方式启动了这个动画旋转类。
mHeaderImageView.startAnimation(mFlipAnimation);
接着init最后一句代码addHeaderView()把头部的refreshView给添加进来。
private void addHeaderView() {
// header view
mHeaderView = mInflater.inflate(R.layout.refresh_header, this, false);
mHeaderImageView = (ImageView) mHeaderView
.findViewById(R.id.pull_to_refresh_image);
mHeaderTextView = (TextView) mHeaderView
.findViewById(R.id.pull_to_refresh_text);
mHeaderUpdateTextView = (TextView) mHeaderView
.findViewById(R.id.pull_to_refresh_updated_at);
mHeaderProgressBar = (ProgressBar) mHeaderView
.findViewById(R.id.pull_to_refresh_progress);
// header layout
measureView(mHeaderView);
mHeaderViewHeight = mHeaderView.getMeasuredHeight();
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,
mHeaderViewHeight);
// 设置topMargin的值为负的header View高度,即将其隐藏在最上方
params.topMargin = -(mHeaderViewHeight);
// mHeaderView.setLayoutParams(params1);
addView(mHeaderView, params);
}
其中关键代码在最后几句,measureView(mHeaderView)对子控件mHeaderView进行了测量,然后才能把这个子控件塞进
PullToRefreshView,说得通熟易懂点,就是当你自定义组件时,如果要往父控件里面放入其他子控件,那么你的父控件会首先问你子控件需要多大一块地方,你给了这个宽高之后我才能把你放进来,measureView(View child)中最后一句child.measure(childWidthSpec, childHeightSpec);就是设置了子控件的宽高,到时候父控件就会给你那么大块地方。需要注意的是,View.measure这个方法中,实际上调用了View.onMeasure这个方法,而这个方法才是自定义组件中经常会重写的一个测量方法,具体可以搜搜网上的用法。
上面的代码段中还有一句params.topMargin = -(mHeaderViewHeight);这里就是为什么当你下拉时才会看见那个刷新view,是因为这个头部刷新条将自己隐藏起来了,做法就是子view与父view上边界的距离等于子view自身高度的负值,这样就可以正好隐藏自己。接下里就把这个上拉刷新view添加到父view中,然后下拉加载的view也是几乎同样的道理,唯一的不同点在于,由于是线性布局可以直接添加,只要AdapterView的高度是MATCH_PARENT,那么footer view就会被添加到最后,并隐藏。
addFooterView没有直接在init方法中,而是放到了下面的方法中。
@Override
protected void onFinishInflate() {
super.onFinishInflate();
// footer view 在此添加保证添加到linearlayout中的最后
addFooterView();
initContentAdapterView();
}
这里重写了View.onFinishInflate方法,当View和它的所有子对象从XML中导入之后,此方法才会被回调,这样,前面前面的顺序都排好了,这里再添加个foot refreshView,就能保证把它添加到最后,不然有可能添加到AdapterView的前面。
接着说,下面的initContentAdapterView方法是对列表的初始化,就不多说了。
上面将各个组件都初始化并测量加载之后,就要开始各种监听以及判断处理了,我们第二篇再接着讲。下面先附上代码,不好意思加了一分竟然不能编辑改下分数,大家也可以直接搜下PullToRefreshView看看哪里有没有免费的下载,懒得改了。
http://download.csdn.net/detail/baozhuifeng/5892305