商品详情页RecyclerView与TabLayout的联动定位
code小生 ,一个专注大前端领域的技术平台
公众号回复 Android 加入我的技术群
作者: Small_Cake
链接: https://www.jianshu.com/p/5df93040e126
声明:
本文已获
Small_Cake
授权发表,转发等请联系原作者授权
要考虑两方面的交互:
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 && 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

最后的效果图:
滚动到指定位置, tab变
原文链接: https://www.jianshu.com/p/5df93040e126