针对自定义组件上拉刷新下拉加载更多PullToRefreshView的分析(一)

本文介绍了自定义组件PullToRefreshView的使用,它支持ListView、GridView和ScrollView的刷新操作。文章重点分析了组件的工作原理,包括如何在下拉时显示刷新视图、触摸事件处理、动画效果以及布局设计。代码实现中,通过继承LinearLayout并实现监听接口,实现了上拉和下拉刷新的功能。此外,文章还讨论了如何隐藏头部刷新视图以及在View导入后添加底部加载视图的时机。
摘要由CSDN通过智能技术生成

首先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











 



评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值