首先PullToRefreshView是一个上拉刷新下拉加载的一个自定义组件,它支持三种view,ListView,GridView和ScrollView的刷新操作,这里就针对其中自己觉得比较有用的一部分进行分析。代码会放在下面。在下有的地方也不是很懂,如果有不对的地方请指正。先给个图找找感觉。
转载请注明出处:https://i-blog.csdnimg.cn/blog_migrate/d8bb591129fe273f5b89808a01c7f611.png
在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();
- }
- mHeaderImageView.startAnimation(mFlipAnimation);
- 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);
- }
上面的代码段中还有一句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看看哪里有没有免费的下载,懒得改了。