要考慮兩方面的交互:
1.RecyclerView滾動到一定位置硼一,TabLayout需要指示到對應(yīng)的選項
2.TabLayout點擊對應(yīng)的選項菜單遵倦,RecyclerView要滾動到指定位置
- 由于系統(tǒng)原生TabLayout無法滿足指示器圓角且和字一樣寬的需求,所以我的TabLayout使用的是 MagicIndicator
1.監(jiān)聽RecyclerView的滾動事件
//滾動顯示頂部菜單欄额嘿,onScrollStateChanged執(zhí)行優(yōu)先于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; //滑動的距離
//滾動距離和導(dǎo)航欄高度算出透明度瘸恼,實現(xiàn)上滑隱藏,下滑漸現(xiàn)
float alp = (float) scrollHeight / (float) DpPxUtils.dp2px(80);
mBinding.layoutMenu.setAlpha(alp);
}
});
當(dāng)RecyclerView
滾動停止時:我們使用Handler
來進行通知TabLayout
來選定對應(yīng)選項册养。同時我們還通過isClickTab
參數(shù)來屏蔽掉點擊TabLayout導(dǎo)致的滾動东帅,其中的myHandler為:
class MyHandler extends Handler {
private WeakReference<Activity> reference;
public MyHandler(Activity activity) {
reference = new WeakReference<Activity>(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;
}
}
}
}
這里我們使用弱引用的方式創(chuàng)建Handler 對象,避免內(nèi)存泄露球拦。其中的
-
magicIndicator
:頂部指示器靠闭。 -
topBannerAndInfoHeight
:商品高度 -
topGoodsPicHeight
:詳情高度
2.點擊TabLayout讓RecyclerView滾動到指定位置
//tabLayout和RecyclerView聯(lián)動事件
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
創(chuàng)建指示器包含了固定的大量代碼,我封裝了一個工具類來創(chuàng)建坎炼,并把點擊事件傳遞出來愧膀。TabCreateUtils
工具類如下:
//菜單指示器創(chuàng)建工具類
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
最后的效果圖: