很长时间没有写过博客了感觉有点紧张(怎么可能呢 哈哈) ,这几天在公司项目的开发中,看到同行中一个挺好看的功能,就滑着玩了会,感觉体验挺好的,我百忙中抽出时间去研究了一下,居然效果也挺不错,然后就说服iOS那哥们,一块把这个功能同步到项目中,接下来就带你去看看。
效果图:
先不要考虑什么内容,从技术的角度来看,这种效果感觉很不错,用户体验也挺棒,具体怎么实现呢,接着往下看:
首先咱们列表里滑动的item目前基本上是 RecycleView和ListView 来实现的,这里我选择第一种 RecycleView,我项目中分为三层嵌套(MainActivity->TabHomeClassifyFragment->AnchorListFragment),MainActivity:这里面主要是自定义RadioGroup来实现的导航Veiw,如图 :
TabHomeClassifyFragment:这里面主要是用来承载Fragment和上面的TabLayout(这里我自定义的CustomPagerIndicator 这个可以动态修改指示器动画长度以及title的颜色渐变等),代码:
AnchorListFragment则是最底那一层也就是RecycleView和置顶View)
首先咱们得监听一下RecycleView的滑动偏移量来 来判断它的滑动方向 代码在这:
public void setRecyclerScrollListener(boolean isUsered, RecyclerView recyclerView) {
if (recyclerView == null) return;
if (isUsered) {
recyclerView.addOnScrollListener(recyclerScrollListener);
} else {
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (distance > THRESHOLD && visible) {
if (listener != null) {
visible = false;
distance = 0;
listener.onHideView();
}
} else if (distance < -20 && !visible) {
if (listener != null) {
visible = true;
distance = 0;
listener.onShowView();
}
}
if (visible && dy > 0 || (!visible && dy < 0)) {
distance += dy;
}
}
});
}
}
这是用来判断滑动距离 是否可见的,我这里是用的一个类来处理滑动监听的逻辑,因为还有其他的业务逻辑,果断抽出来了,这是在AnchorListFragment中进行监听的,通过接口的形式回调到此fragment中
这就是回调回来的是否显示或者隐藏View,因为这里就是置顶view 如果不处理的话AppBarLayout展开的话这个view就会被挤到屏幕外(view在右下角贴边)所以得在TabHomeClassifyFragment通过监听AppBarLayout的addOnOffsetChangedListener来动态去设置这个View的高度,代码如下:
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
if (ivRecommendtop == null) return;
if (ivRecommendtop.getVisibility() == View.GONE) return;
if (verticalOffset < -1) {
ViewUtils.setMarginBottom(ivRecommendtop, ViewUtils.dp2px(100));
} else {
ViewUtils.setMarginBottom(ivRecommendtop, ViewUtils.dp2px(200));
}
}
接着咱来看TabHomeClassifyFragment的xml:
frameLayout会在初始化的时候替换成ViewPager去绑定fragment
然后在这个TabHomeClassifyFragment中通过接口来接收AnchorListFragment中RecycleView滑动而监听到的控制View的显示与隐藏 代码:
private void onShowHideUIListner(int position) {
if (ObjectUtils.isEmpty(mList)) return;
AnchorListFragment fragment = (AnchorListFragment) mList.get(position);
fragment.setOnTouchScrollListener(new AnchorListFragment.OnTouchScrollListener() {
@Override
public void onShow() {
if (lin_top_view != null) {
lin_top_view.bringToFront();
}
if (onTouchScrollListener != null) {
onTouchScrollListener.onShowView();
}
}
@Override
public void onHide() {
if (onTouchScrollListener != null) {
onTouchScrollListener.onHideView();
}
}
});
if (position == 0) {
barlayout.addOnOffsetChangedListener(fragment::onOffsetChanged);
}
fragment.onPageSelected(position);
}
可以看出在这里监听到这个滑动事件后把这个事件接着传递到最外层的MainActivity中 目的是为了让Activity中的RadioGroup根据这个事件去显示或者隐藏,而此时的自定义TabLayout布局会通过CoordinatorLayout 和AppBarLayout来实现上拉隐藏,下拉显示。
最后咱们把事件传递到Activity中 在这:
rvNavBar.animate().translationY(0).setInterpolator(new DecelerateInterpolator(3)); 这是用来显示导航的
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) rg_main.getLayoutParams();
rvNavBar.animate().translationY(rvNavBar.getHeight() + layoutParams.bottomMargin).setInterpolator(new AccelerateInterpolator(3)); 这是用来隐藏导航的
到这里基本已经实现了,里面主要是我项目中业务逻辑比较多,然后去处理这些,最麻烦点的就是通过接口把滑动事件传递给这三层。
然后由于公司项目 不方面上传代码,有需要的或者不懂的同学可以私我,我定全力帮你!