36

商品详情页RecyclerView与TabLayout的联动定位

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzIxNzU1Nzk3OQ%3D%3D&%3Bmid=2247489270&%3Bidx=1&%3Bsn=72e4752338037045aee4612c99409831
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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

这里我们使用弱引用的方式创建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

RFfmUj6.jpg!web image.png

最后的效果图:

i2eQnam.jpg!web

滚动到指定位置, tab变

原文链接: https://www.jianshu.com/p/5df93040e126

B3Q7faa.jpg!web

扫一扫 关注我的公众号

如果你想要跟大家分享你的文章,欢迎投稿~


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK