用behavior实现的
项目地址
实现的效果

preview.gif
建议
请先阅读这篇文章
www.jianshu.com/p/f7989a2a3…
好多东西抄自这里
思路
-
- 都是依赖的Tab
-
- 列表是跟随Tab
-
- 向上的箭头高度是写死的,图标由顶部移动到居中的位置
-
- 刚开始详细的搜索的头部跟全部搜索的头部一致,最终移动到向上箭头的下面
-
- 后面绿色背景也是跟随tab
ListBehvior 的实现
抄自 HeaderScrollingViewBehavior
1 列表的高度计算
//列表高度为=可用高度-依赖的view的高度
final int height = availableHeight - header.getMeasuredHeight();
final int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(height,
childLpHeight == ViewGroup.LayoutParams.MATCH_PARENT
? View.MeasureSpec.EXACTLY
: View.MeasureSpec.AT_MOST);
2 列表的初始位置
available.set(parent.getPaddingLeft() + lp.leftMargin,
header.getBottom() + lp.topMargin,
parent.getWidth() - parent.getPaddingRight() - lp.rightMargin,
parent.getHeight() + header.getBottom()
- parent.getPaddingBottom() - lp.bottomMargin);
3 跟随 Tab移动
//跟随tab移动
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
child.setTranslationY(dependency.getTranslationY());
return true;
}
TabBehavior的实现
1 是否开始嵌套滑动的判断
//只要是垂直方向的就开始
return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0
@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {
mControlChange = true;//手动导致的改变
return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL)
!= 0;
}
2 Scroll的分配
/**
* @param dy 向上滑大于0
*/
@Override
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) {
mUp = dy > 0;//保留记录,是否向上滑动
if (mValueAnimator.isRunning()) {//如果有已经开始的动画,则结束动画
mValueAnimator.cancel();
}
//如果list需要滑动 且 不是(向上滑&&tab不在顶部)
if (isChildRequestScroll(child.getTranslationY())) {
consumed[1] = 0;
return;
}
consumed[1] = dy;//全部消耗
int distance = -dy / 2;//降低移动的速度
if (child.getTranslationY() + distance > mTranslationMax) {//大于最大距离
distance = mTranslationMax;
} else if (child.getTranslationY() + distance < 0) {//到顶部
distance = 0;
} else {//正常
distance = (int) (child.getTranslationY() + distance);
}
//判断应该显示的样式
if (mUp && distance < (mTranslationMin - mHeightChild / 2) && !mWhiteStyle) {
setWhiteStyle();
} else if (!mUp && distance > (mTranslationMin + mHeightChild / 2) && mWhiteStyle) {
setGreenStyle();
}
child.setTranslationY(distance);
}
3 Fling时候的判断
/**
* list 不需要滑动就拦截.需要就不拦截
*/
@Override
public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, View child, View target, float velocityX, float velocityY) {
if (velocityY < -1000 && child.getTranslationY() == 0) {//向下滑的速度小于负1000
mControlChange = false;
showSearchAll();
}
return !isChildRequestScroll(child.getTranslationY());
}
4 Stop时候的判断
@Override
public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target) {
mControlChange = false;
float translationY = child.getTranslationY();
//如果是几个需要停住的点,则不管
if (translationY == mTranslationMax || translationY == mTranslationMin || translationY == 0) {
return;
}
scroll(child, translationY);
}
/**
* 三种情况
* 1 在顶部
* 2 在all的下面
* 3 在condition的下面
*/
private void scroll(final View child, final float translationY) {
final float shouldMoveDistance;
if (translationY < mHeightChild / 2) {//这段去最上面
shouldMoveDistance = -translationY;
} else if ((translationY > mHeightChild / 2 && translationY < (mTranslationMin + mHeightChild / 2)) ||
(mUp && translationY < (mTranslationMax - mHeightChild))) {//回到中间的点
shouldMoveDistance = mTranslationMin - translationY;
} else {//去最下面
shouldMoveDistance = mTranslationMax - translationY;
}
mValueAnimator.setDuration((long) (Math.abs(shouldMoveDistance) / mTranslationMax * Constants.DURATION_SCROLL));
mValueAnimator.removeAllUpdateListeners();
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
child.setTranslationY(translationY + animation.getAnimatedFraction() * shouldMoveDistance);
}
});
mValueAnimator.start();
}
SearchAllBehavior的实现
//最大的位移的高度
mChangeHeight = mHeightUp - mMarginTop;
@Override public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
float translationY = dependency.getTranslationY();
if (translationY < mTranslationMin) {//向上移动的时候跟随tab
//如果在屏幕外面则移动进来
child.setTranslationX(0);
child.setTranslationY(translationY - mTranslationMin);
} else {//展开的时候,根据比例设置
//tab 位移的比例
float fraction = (translationY - mTranslationMin) / (mTranslationMax - mTranslationMin);
//根据比例设置位移的距离
if (fraction <= 1 / 3f) {//跟详细信息里面的where一样的移动
child.setTranslationX(0);
child.setTranslationY(fraction * mChangeHeight);
child.setAlpha(1 - fraction * 3);
} else {
if (child.getTranslationX() != mTranslationGone) {//移动到屏幕外面,重置透明度为0
child.setTranslationX(mTranslationGone);
child.setAlpha(0);
}
}
}
return true;
}
SearchItemBehavior的实现
@Override public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
float translationY = dependency.getTranslationY();
if (translationY >= mTranslationMin) {//开始显示各个item的时候,把child移动到屏幕里面,重置alpha为1
if (child.getTranslationX() != 0) {
child.setTranslationX(0);
child.setAlpha(1);
}
//tab 位移的比例
float fraction = (translationY - mTranslationMin) / (mTranslationMax - mTranslationMin);
//根据比例设置位移的距离
child.setTranslationY(fraction * mChangeHeight);
//根据比例设置透明度
if (fraction < 1 / 3f) {
mItemWhere.setTranslationX(0);
mItemWhen.setTranslationX(mTranslationGone);
mItemWho.setTranslationX(mTranslationGone);
mItemWhere.setAlpha(fraction * 3);
mItemWhen.setAlpha(0);
mItemWho.setAlpha(0);
} else if (fraction < 2 / 3f) {
mItemWhere.setTranslationX(0);
mItemWhen.setTranslationX(0);
mItemWho.setTranslationX(mTranslationGone);
mItemWhere.setAlpha(1);
mItemWhen.setAlpha(fraction * 3 - 1);
mItemWho.setAlpha(0);
} else {
mItemWhere.setTranslationX(0);
mItemWhen.setTranslationX(0);
mItemWho.setTranslationX(0);
mItemWhere.setAlpha(1);
mItemWhen.setAlpha(1);
mItemWho.setAlpha(fraction * 3 - 2);
}
} else if (child.getTranslationX() != mTranslationGone) {//改隐藏的时候移动到屏幕外面
child.setTranslationX(mTranslationGone);
child.setAlpha(0);
}
return true;
}
UpIconBehavior的实现
@Override public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
float translationY = dependency.getTranslationY();
float fraction = (translationY - mTranslationMin) / (mTranslationMax - mTranslationMin);
//根据比例设置位移的距离
if (fraction >= 1 / 3f) {
child.setTranslationX(0);
float fractionItem = (fraction * 3 - 1) / 2;
child.setTranslationY(-(1 - fractionItem) * mChangeHeight);
child.setAlpha(fractionItem);
} else if (child.getTranslationX() != mTranslationGone) {
child.setTranslationX(mTranslationGone);
child.setAlpha(0);
}
return true;
}
BGBehavior的实现
@Override public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
child.setTranslationY(dependency.getTranslationY()-mTranslationMax);
return true;
}