之前写过一个ActionBar随着列表或者其他滑动而显示或者隐藏的文章,前段时间,有了新的想法了,所以,更新一下代码,把新的思路放上来。(最新的android design support包当中,已经有类似功能的封装了,但是貌似不够灵活,还没有仔细研究那个包呢)
原文地址:http://blog.csdn.net/boybeak/article/details/41410113
新视线思路的Github地址:https://github.com/boybeak/ScrollTrack
如果你会科学上网法,可以去PlayStore安装应用:https://play.google.com/store/apps/details?id=com.beak.scrolltrack
视频演示如下:
http://v.youku.com/v_show/id_XMTM1NzQ3ODA5Mg==.html?from=y1.7-1.2#paction
基本思路:
主要是利用RecyclerView 的OnScrollListener的两个回调函数OnScrollStateChange和OnScrolled,去控制指定view的显示,位置和隐藏,再利用动画,使动作更为流畅。
在代码中,有两个类:TopTrackListener和BottomTrackListener,分别用来控制向上隐藏和向下隐藏。这样的思路,可以移植到其他的可以随手滑动的控件上。
废话不多说,以TopTrackListener为例,代码如下:
public class TopTrackListener extends RecyclerView.OnScrollListener {
private static final String TAG = TopTrackListener.class.getSimpleName();
private int mLastDy = 0;
private int mTotalDy = 0;
private View mTargetView = null;
private ObjectAnimator mAnimator = null;
private boolean isAlreadyHide = false, isAlreadyShow = false;
public TopTrackListener(View target) {
if (target == null) {
throw new IllegalArgumentException("target shouldn't be null");
}
mTargetView = target;
}
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
switch (newState) {
case RecyclerView.SCROLL_STATE_IDLE:
final float transY = mTargetView.getTranslationY();
int distance = -mTargetView.getBottom();
if (transY == 0 || transY == distance) {
return;
}
if (mLastDy > 0) {
mAnimator = animateHide(mTargetView);
} else {
mAnimator = animateShow(mTargetView);
}
break;
case RecyclerView.SCROLL_STATE_DRAGGING:
if (mAnimator != null && mAnimator.isRunning()) {
mAnimator.cancel();
}
break;
case RecyclerView.SCROLL_STATE_SETTLING:
break;
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
mTotalDy -= dy;
mLastDy = dy;
final float transY = mTargetView.getTranslationY();
float newTransY;
int distance = -mTargetView.getBottom();
if (mTotalDy >= distance && dy > 0) {
return;
}
if (isAlreadyHide && dy > 0) {
return;
}
if (isAlreadyShow && dy < 0) {
return;
}
newTransY = transY - dy;
if (newTransY < distance) {
newTransY = distance;
} else if (newTransY == distance) {
return;
} else if (newTransY > 0) {
newTransY = 0;
} else if (newTransY == 0) {
return;
}
mTargetView.setTranslationY(newTransY);
isAlreadyHide = newTransY == distance;
isAlreadyShow = newTransY == 0;
}
private ObjectAnimator animateHide (View targetView) {
int distance = -targetView.getBottom();
return animationFromTo(targetView, targetView.getTranslationY(), distance);
}
private ObjectAnimator animateShow (View targetView) {
return animationFromTo(targetView, targetView.getTranslationY(), 0);
}
private ObjectAnimator animationFromTo (View view, float start, float end) {
String propertyName = "translationY";
ObjectAnimator animator = ObjectAnimator.ofFloat(view, propertyName, start, end);
animator.start();
return animator;
}
}