TabLayout使用

当我们要实现多个tab切换时,当然可以自己布局去实现,但这个需要自己处理一些事情(比如下划线的滑动等,虽然这也不难),更简单的实现方式就是使用TabLayout去实现,下面我来总结一下TabLayout的使用。


一、使用步骤

1、导入support依赖:

compile 'com.android.support:design:25.3.1'

在导入support包的时候可能会导致65536超出方法数的异常,请参考 异常com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536

2、布局




    

        

        

    

上面是一个简单但通用的 TabLayout + ViewPager 布局页面,由于我使用了databinding框架,所以外面多了一层layout标签。TabLayout的属性我不做过多解释。

3、设置主题样式

如果按照现在这样运行,会异常,因为TabLayout需要设置样式

Theme.AppCompat
既可以在清单文件中设置,也可以代码设置,为了通用,我是代码设置的:

setTheme(R.style.Theme_AppCompat);
注意必须在setContentView()之前设置才有效。

4、设置tab和ViewPager

    protected void setTitleAndContent(List titles, ArrayList fragments) {
        if (titles == null || titles.size() <= 0 || fragments == null || fragments.size() <= 0) {
            ToastViewUtil.showShort(mContext, "标题和内容不能为空!");
            return;
        }
        if (titles.size() != fragments.size()) {
            ToastViewUtil.showShort(mContext, "标题和内容数目不一致!");
            return;
        }

        mBinding.tabLayout.setupWithViewPager(mBinding.pager);
        mBinding.pager.setAdapter(new AdapterTabPagerFragment(getSupportFragmentManager(), fragments));
        mBinding.pager.addOnPageChangeListener(this);

        for (int i=0; i
这里注意,setupWithViewPager()必须在tab的setText()之前,不然tab上面的内容会显示不出来。

ViewPager滑动事件绑定tab选择:

    @Override
    public void onPageSelected(int position) {
        mBinding.tabLayout.getTabAt(position).select();
    }
5、一个蛋疼的问题

这个时候运行程序,你会发现tab下面的下划线很长,它的宽度是跟tab的宽度一致的,然而并没有方法设置下划线的宽度。OMG。。。。。这个时候自定义控件的优势显现出来了,想设多长就设多长。

然而,这等问题是难不倒天朝程序员的,百度一下,发现大家解决这个问题的方案基本都是通过反射的方式设置下划线的margin,我把这个方法做了优化,让下划线永远是tab宽度的一半,先计算的tab的宽度,这个简单,就是屏幕宽度除以tab数量:

tabIndicatorWidth = getWindowManager().getDefaultDisplay().getWidth() / (2 * titles.size());
修改后的设置下划线宽度的方法:

/**
     * 设置下标线的宽度
     *
     * @param tabs
     */
    public void setIndicatorWidth(TabLayout tabs) {
        Class tabLayout = tabs.getClass();
        Field tabStrip = null;
        try {
            tabStrip = tabLayout.getDeclaredField("mTabStrip");
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }

        tabStrip.setAccessible(true);
        LinearLayout llTab = null;
        try {
            llTab = (LinearLayout) tabStrip.get(tabs);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        for (int i = 0; i < llTab.getChildCount(); i++) {
            View child = llTab.getChildAt(i);
            child.setPadding(0, 0, 0, 0);
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 1);
            params.leftMargin = tabIndicatorWidth / 2;
            params.rightMargin = tabIndicatorWidth / 2;
            child.setLayoutParams(params);
            child.invalidate();
        }
    }
这里是通过设置leftMargin和rightMargin来间接设置下划线的宽度。

由于需要在UI绘制完成之后调用该方法才有用,所以使用post()方法来调用该方法:

        mBinding.tabLayout.post(new Runnable() {
            @Override
            public void run() {
                setIndicatorWidth(mBinding.tabLayout);
            }
        });

其他问题:

1、tab的字体大小不能直接精确设置,只能通过

app:tabTextAppearance="@style/TextAppearance.AppCompat.Menu"
来设置。


参考:

Design库-TabLayout属性详解




你可能感兴趣的:(android学习)