仿折叠布局的上滑隐藏下滑显示动画
应产品要求,做一个效果,上滑滑出界面,下滑显示,本来可以直接使用系统原生的折叠布局,可偏偏与要求不符。
传统方式:
fragment/activity中tab+recylerview,列表滑动带动tab隐藏显示。
产品要求的方式:
tab+viewPager
viewpager子布局为由 search layout+recylerview组成的多个fragment(每个fragment布局不一致)
tab+fragment中的搜索框上滑隐藏,下滑显示。
实现思路:
1.监听recylerview的onScroll事件,当事件发生变更,通知当前fragment及父类fragment隐藏当前布局。
2.隐藏动画的实现(这里把布局高度写死了)。
3.后续细节完善。
数据为空时,reyclerview不能滑动,也就不会回调scroll方法了,只能在下拉刷新监听中手动显示布局(当前为隐藏状态)。
数据不足一屏时,reyclerview也不能滑动,这时在上拉加载监听中手动隐藏布局(当前为显示状态)。
到这里,实现是实现功能了,不过遇到了一个小bug,当快速滑动或轻微点击的时候,动画会在显示隐藏之间不停切换。
打印发现问题:
1.当前状态为布局隐藏状态时,下滑显示,会改变recylerviewY轴偏移量,使得recylerview快速滑动,因此判断条件加上reyclerview不为快速滑动。
2.防止用户误操作,偏移量设置大一点,另外时间限制长点,不然用户体验不好。
具体代码:
1..监听recylerview的onScroll事件,当事件发生变更,通知当前fragment及父类fragment隐藏当前布局。
mList.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
Log.e("fg", "dx:" + dx + "---dy:" + dy);
//上滑隐藏
if (dy > 1) {
if (!isScrollUp && System.currentTimeMillis() - time > 1000 && mList.getScrollState()!= RecyclerView.SCROLL_STATE_SETTLING) {
time = System.currentTimeMillis();
isScrollUp = true;
EventBus.getDefault().post(true, Constants.IS_REFRESH);
}
//下滑显示
} else if (dy < -1) {
if (isScrollUp && System.currentTimeMillis() - time > 1000 && mList.getScrollState()!= RecyclerView.SCROLL_STATE_SETTLING) {
time = System.currentTimeMillis();
isScrollUp = false;
EventBus.getDefault().post(false, Constants.IS_REFRESH);
}
}
super.onScrolled(recyclerView, dx, dy);
}
});
2.接收事件,实现隐藏/显示动画。
@Subscriber(tag = Constants.IS_REFRESH)
public void updateHeader(Boolean isHideHeader) {
if (isHideHeader) {
showHideTitle(llLayout, 0, 4, false);
} else {
showHideTitle(llLayout, DeviceUtils.dpToPixel(getContext(), 44), 4, true);
}
}
public static void showHideTitle(final View view, final int maxHeight, int duration, boolean isShow) {
ValueAnimator animator;
if (isShow) {
animator = ValueAnimator.ofFloat(0f, 1f);
} else {
animator = ValueAnimator.ofFloat(1f, 0f);
}
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float currentValue = (float) animation.getAnimatedValue();
ViewGroup.LayoutParams params = view.getLayoutParams();
params.height = (int) (currentValue * maxHeight);
view.setLayoutParams(params);
}
});
animator.setDuration(duration).start();
}
}
实现效果:
~题外话:
我也不知道写了这个有什么用,其实很简单,只要理解实现思路就好了,可是记着就记着吧,万一以后又遇到这种类似问题,留个储备。
知道自己还有很多不足,我觉得应该正视,从来不觉得自己有多能耐,只能一路慢慢啃。路还长着呢~