ViewPager+RecyclerView分页菜单栏

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

分页菜单图

想做一个如上图的横向分页菜单栏,最先在网上找了一圈,看到这个使用RecyclerView实现多行水平分页的GridView效果和ViewPager效果还不错,但感觉要自定义四个文件,要复制一大堆,我懒,所以就没怎么仔细看它的分页自定义了。所以我打算还是用ViewPager来分页吧,每页用一个RecyclerView来装载固定的数据就可以了。

1.布局:
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <android.support.v4.view.ViewPager
                    android:id="@+id/view_pager"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" />

                <net.lucode.hackware.magicindicator.MagicIndicator
                    android:id="@+id/tab_layout"
                    android:layout_width="66dp"
                    android:layout_height="8dp"
                    android:layout_gravity="center"
                    android:background="@drawable/round_orange_rim_white_bg" />

            </LinearLayout>

其中用到了MagicIndicator这款指示器,可以自定义非常灵活,尽管我懒得自定义。

2.初始化ViewPager
public class CoordinatorLayoutTestFragment extends BaseFragment {
    @BindView(R.id.view_pager)
    ViewPager viewPager;
    @BindView(R.id.magic_indicator)
    MagicIndicator magicIndicator;
    @Override
    public int setLayout() {
        return R.layout.fragment_coordinatorlayout_test;
    }
    @Override
    protected void onBindView(View view, ViewGroup container, Bundle savedInstanceState) {
        initViewPager(getData(), 2, 4);
    }
    /**
     * @param datas   所有数据
     * @param rowNum  行数
     * @param spanNum 列数
     */
    private void initViewPager(ArrayList<MenuItem> datas, int rowNum, int spanNum) {
        //1.根据数据的多少来分页,每页的数据为rw
        int singlePageDatasNum = rowNum * spanNum;//每个单页包含的数据量:2*4=8;
        int pageNum = datas.size() / singlePageDatasNum;//算出有几页菜单:20%8 = 3;
        if (datas.size() % singlePageDatasNum > 0) pageNum++;//如果取模大于0,就还要多一页出来,放剩下的不满项
        ArrayList<RecyclerView> mList = new ArrayList<>();
        for (int i = 0; i < pageNum; i++) {
            RecyclerView recyclerView = new RecyclerView(_mActivity);
            GridLayoutManager gridLayoutManager = new GridLayoutManager(_mActivity, spanNum);
            recyclerView.setLayoutManager(gridLayoutManager);
            int fromIndex = i * singlePageDatasNum;
            int toIndex = (i + 1) * singlePageDatasNum;
            if (toIndex > datas.size()) toIndex = datas.size();
            //a.截取每个页面包含数据
            ArrayList<MenuItem> menuItems = new ArrayList<>(datas.subList(fromIndex, toIndex));
            //b.设置每个页面的适配器数据
            MainMenuAdapter menuAdapter = new MainMenuAdapter();
            menuAdapter.setNewData(menuItems);
            //c.绑定适配器,并添加到list
            menuAdapter.bindToRecyclerView(recyclerView);
            recyclerView.setAdapter(menuAdapter);
            mList.add(recyclerView);
        }
        //2.ViewPager的适配器
        MenuViewPagerAdapter menuViewPagerAdapter = new MenuViewPagerAdapter(mList);
        viewPager.setAdapter(menuViewPagerAdapter);
        //3.动态设置ViewPager的高度,并加载所有页面
        int height = DpPxUtils.dp2px(80);//这里的80为MainMenuAdapter中布局文件高度
        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, datas.size()<=spanNum?height:height * rowNum);
        viewPager.setLayoutParams(layoutParams);
        viewPager.setOffscreenPageLimit(pageNum - 1);
        //4.创建指示器
        CommonNavigator commonNavigator = new CommonNavigator(_mActivity);
        commonNavigator.setAdjustMode(true);
        int finalPageNum = pageNum;
        commonNavigator.setAdapter(new CommonNavigatorAdapter() {
            @Override
            public int getCount() {
                return finalPageNum;
            }

            @Override
            public IPagerTitleView getTitleView(Context context, int index) {
                return new DummyPagerTitleView(context);
            }

            @Override
            public IPagerIndicator getIndicator(Context context) {
                LinePagerIndicator indicator = new LinePagerIndicator(context);
                indicator.setMode(LinePagerIndicator.MODE_EXACTLY);
                indicator.setLineHeight(UIUtil.dip2px(context, 8));//就是指示器的高
                indicator.setLineWidth(UIUtil.dip2px(context, 66/finalPageNum));//就是指示器的宽度,然后通过页数来评分
                indicator.setRoundRadius(UIUtil.dip2px(context, 8));
                indicator.setStartInterpolator(new AccelerateInterpolator());
                indicator.setEndInterpolator(new DecelerateInterpolator(3));
                indicator.setColors(ContextCompat.getColor(context,R.color.colorAccent));
                return indicator;
            }
        });
        //5.配置指示器,并和ViewPager产生绑定
        magicIndicator.setNavigator(commonNavigator);
        ViewPagerHelper.bind(magicIndicator, viewPager);
    }
    private ArrayList<MenuItem> getData() {
        ArrayList<MenuItem> list = new ArrayList<>();
        for (int i = 0; i < 22; i++) {
            list.add(new MenuItem(R.mipmap.ic_launcher_round, "SmallCake" + (i+1)));
        }
        return list;
    }
}

其中的MenuItem就是菜单的类,每个人不同,自己写吧。关键点就是根据行数和列数得到每页总数,然后根据数据量的数目算出有好多页就行了。
还有ViewPager的分页适配器为:MenuViewPagerAdapter:

public class MenuViewPagerAdapter extends PagerAdapter {
    private ArrayList<RecyclerView> mList;
    public MenuViewPagerAdapter(ArrayList<RecyclerView> mList) {
        this.mList = mList;
    }
    @Override
    public int getCount() {
        return mList.isEmpty() ? 0 : mList.size();
    }
    @Override
    public boolean isViewFromObject(@NonNull View view, @NonNull Object o) {
        return view==o;
    }
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView(mList.get(position));
    }
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        container.addView(mList.get(position));
        return mList.get(position);
    }
}

感觉比自定义简单,最后的效果就出来了:


分页菜单
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342