Tears_fg

导航

仿折叠布局的上滑隐藏下滑显示动画

应产品要求,做一个效果,上滑滑出界面,下滑显示,本来可以直接使用系统原生的折叠布局,可偏偏与要求不符。

传统方式

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();
    }

}

实现效果:

 

~题外话:

我也不知道写了这个有什么用,其实很简单,只要理解实现思路就好了,可是记着就记着吧,万一以后又遇到这种类似问题,留个储备。

知道自己还有很多不足,我觉得应该正视,从来不觉得自己有多能耐,只能一路慢慢啃。路还长着呢~

posted on 2019-12-02 14:29  Tears_fg  阅读(1058)  评论(0编辑  收藏  举报