要考虑两方面的交互:
1.RecyclerView滚动到一定位置,TabLayout需要指示到对应的选项
2.TabLayout点击对应的选项菜单,RecyclerView要滚动到指定位置
- 由于系统原生TabLayout无法满足指示器圆角且和字一样宽的需求,所以我的TabLayout使用的是 MagicIndicator
1.监听RecyclerView的滚动事件
//滚动显示顶部菜单栏,onScrollStateChanged执行优先于onScrolled方法
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
switch (newState) {
case RecyclerView.SCROLL_STATE_IDLE://滚动停止
if (isClickTab)myHandler.sendEmptyMessage(1);
else myHandler.sendEmptyMessage(0);
break;
case RecyclerView.SCROLL_STATE_DRAGGING://手指 拖动
break;
case RecyclerView.SCROLL_STATE_SETTLING://惯性滚动
break;
}
}
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
scrollHeight += dy; //滑动的距离
//滚动距离和导航栏高度算出透明度,实现上滑隐藏,下滑渐现
float alp = (float) scrollHeight / (float) DpPxUtils.dp2px(80);
mBinding.layoutMenu.setAlpha(alp);
}
});
当RecyclerView
滚动停止时:我们使用Handler
来进行通知TabLayout
来选定对应选项。同时我们还通过isClickTab
参数来屏蔽掉点击TabLayout导致的滚动,其中的myHandler为:
class MyHandler extends Handler {
private WeakReference reference;
public MyHandler(Activity activity) {
reference = new WeakReference(activity);
}
@Override
public void handleMessage(Message msg) {
if (reference.get() != null) {
switch (msg.what) {
case 0:
//停止位置为【商品】
if (scrollHeight <= topBannerAndInfoHeight) {
mBinding.magicIndicator.onPageSelected(0);
//停止位置为【详情】
} else if (scrollHeight > topBannerAndInfoHeight && scrollHeight <= topGoodsPicHeight) {
mBinding.magicIndicator.onPageSelected(1);
//停止位置为【喜欢】
} else {
mBinding.magicIndicator.onPageSelected(2);
}
break;
case 1://如果是点击的tab,不重新选择选项卡
isClickTab=false;
break;
}
}
}
}
这里我们使用弱引用的方式创建Handler 对象,避免内存泄露。其中的
-
magicIndicator
:顶部指示器。 -
topBannerAndInfoHeight
:商品高度 -
topGoodsPicHeight
:详情高度
2.点击TabLayout让RecyclerView滚动到指定位置
//tabLayout和RecyclerView联动事件
String[] names = new String[]{"商品", "详情", "喜欢"};
TabCreateUtils.setWhiteTab(_mActivity, magicIndicator, names, index -> {
if (scrollHeight == 0) return;
isClickTab=true;
switch (index) {
case 0://商品
mBinding.recyclerView.smoothScrollToPosition(0);
break;
case 1://详情
int y = topBannerAndInfoHeight - scrollHeight;
mBinding.recyclerView.smoothScrollBy(0, y);
break;
case 2://推荐
mBinding.recyclerView.smoothScrollToPosition(3);
break;
}
});
由于magicIndicator
创建指示器包含了固定的大量代码,我封装了一个工具类来创建,并把点击事件传递出来。TabCreateUtils
工具类如下:
//菜单指示器创建工具类
public class TabCreateUtils {
public interface onTitleClickListener{
void onTitleClick(int index);
}
public static void setWhiteTab(Context context,MagicIndicator magicIndicator, String[] tabNames ,onTitleClickListener listener) {
FragmentContainerHelper mFragmentContainerHelper = new FragmentContainerHelper();
CommonNavigator commonNavigator = new CommonNavigator(context);
commonNavigator.setAdapter(new CommonNavigatorAdapter() {
@Override
public int getCount() {
return tabNames == null ? 0 : tabNames.length;
}
@Override
public IPagerTitleView getTitleView(Context context, final int index) {
SelectBigPagerTitleView colorTransitionPagerTitleView = new SelectBigPagerTitleView(context);
colorTransitionPagerTitleView.setNormalColor(ContextCompat.getColor(context, R.color.white));
colorTransitionPagerTitleView.setSelectedColor(ContextCompat.getColor(context, R.color.white));
colorTransitionPagerTitleView.setText(tabNames[index]);
colorTransitionPagerTitleView.setOnClickListener(view -> {
mFragmentContainerHelper.handlePageSelected(index);
if (listener!=null)listener.onTitleClick(index);
});
return colorTransitionPagerTitleView;
}
@Override
public IPagerIndicator getIndicator(Context context) {
LinePagerIndicator indicator = new LinePagerIndicator(context);
indicator.setMode(LinePagerIndicator.MODE_WRAP_CONTENT);
indicator.setColors(ContextCompat.getColor(context, R.color.white));
indicator.setRoundRadius(3);
return indicator;
}
});
commonNavigator.setAdjustMode(true);
magicIndicator.setNavigator(commonNavigator);
mFragmentContainerHelper.attachMagicIndicator(magicIndicator);
}
}
其中SelectBigPagerTitleView
就是让选中的字体变大,代码如下:
public class SelectBigPagerTitleView extends ColorTransitionPagerTitleView {
public SelectBigPagerTitleView(Context context) {
super(context);
}
@Override
public void onSelected(int index, int totalCount) {
setTextSize(16);
}
@Override
public void onDeselected(int index, int totalCount) {
setTextSize(14);
}
}
布局文件也很简单,就是顶部一坨菜单,底部一坨操作,中间就是RecyclerView
最后的效果图:
原文链接:https://www.jianshu.com/p/5df93040e126