直接进入主题,先来看一下京东的实现效果:
以及我自己的实现效果:
实现过程
1.下拉原理
整个布局为继承自LinearLayout的Viewgroup,分为头部及下面的列表部分,通过设置HeaderView的topMargin属性为负使HeaderView向屏幕上方偏移。
初始化时设置HeaderView的topMargin为负的HeaderView的高度可以将HeaderView完全隐藏,从而屏幕中只看得到列表部分。下拉过程中根据手指划过的距离不断更新HeaderView的topMargin值来改变HeaderView的可视范围从而达到下拉的效果。
2.效果实现
观察京东客户端的下拉过程,可以看出下拉过程中快递员和包裹是不断放大的并且透明度在增加,当HeaderView完全可见时达到最大值并且快递员“取到”包裹,松开手后快递员开始“拼命送货”。
其中放大效果我是用ScaleDrawable实现,通过手指划过的位移改变Drawable的level从而改变图片的大小,不熟悉ScaleDrawable的可以参考Android Drawable之ScaleDrawable。松开手后快递员奔跑是由帧动画实现。
3.关键代码
拦截部分:
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mTouchY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
float dy = event.getY() - mTouchY;
//当RecyclerView移到顶部并且手指向下滑动时,拦截事件,由自己处理Touch事件
if (dy > 0 && canPull)
return true;
case MotionEvent.ACTION_UP:
default:
break;
}
return false;
}
滑动部分:
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
float dy = event.getY() - mTouchY;
mTouchY = event.getY();
if (Math.abs(mTouchY)<touchSlop)
break;
if (mCurrentStatus != STATUS_REFRESHING) {
//除以2是增加下拉的阻力感
headerLayoutParams.topMargin += dy / 2;
//此时为向上滑动到头部完全隐藏的情况,继续滑动的话应该交由RecyclerView处理了,故返回false自己不消耗事件。
if (headerLayoutParams.topMargin<=hideHeaderHeight){
headerLayoutParams.topMargin=hideHeaderHeight;
mHeaderView.requestLayout();
return false;
}
//此时为头部完全显示的情况
if (headerLayoutParams.topMargin>=0){
mCurrentStatus = STATUS_RELEASE_TO_REFRESH;
}else {
mCurrentStatus = STATUS_PULL_TO_REFRESH;
//改变图片的大小及透明度
onLevelChanged((hideHeaderHeight-headerLayoutParams.topMargin)*100/hideHeaderHeight);
}
mHeaderView.requestLayout();
}
break;
case MotionEvent.ACTION_UP:
if (mCurrentStatus == STATUS_PULL_TO_REFRESH){
//属性动画实现平滑滚动
headerAnimation(headerLayoutParams.topMargin,hideHeaderHeight,350,null);
}else if (mCurrentStatus == STATUS_RELEASE_TO_REFRESH){
mCurrentStatus = STATUS_REFRESHING;
headerAnimation(headerLayoutParams.topMargin,0,250,null);
if (listener!=null)
listener.onRefresh();
}
break;
}
updateHeaderView();
lastStatus = mCurrentStatus;
return super.onTouchEvent(event);
}
<br />
具体代码可以参考https://github.com/tangr2015/JDPullToRefresh
<br />
<br />