TabLayout的使用分享

一、概述

相信大家实际开发中会经常碰到需要实现类似于网易新闻Tab标签效果的界面,为了加快开发效率,以前会经常使用到JakeWharton大神的开源框架Viewpager Indicator,框架好是好,但是毕竟比较旧了。其实Google官方也提供了一个TabLayout控件来实现类似的效果。

TabLayout是Google提供的design包中的一个控件,其实现的效果类似于Viewpager Indicator中TabPageIndicator的效果,但是也提供了更多的功能。与TabpagerIndicator相比,TabLayout的优势:

  • 使用更加方便
  • 可以方便的自定义Tab上显示的View
  • 提供了对Tab点击事件的监听方式(单次点击监听,重复点击监听)
  • Tab的指示器带一个动画效果
使用之前我们需要添加design包:
Android Studio中在Gradle中添加:compile 'com.android.support:design:23.1.0'
Eclipse则需要手动添加SDK下\extras\android\support\design\libs中的Jar包

二、TabLayout的使用

先来看看最简单的使用。我们先写这样一个布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.design.widget.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabIndicatorColor="#00eeff"
        app:tabSelectedTextColor="#00eeff"
        app:tabTextColor="#000000" />

    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>
我们可以看到TabLayout中使用了三个属性
   tabIndicatorColor            指示器(下划线)的颜色
   tabTextColor                    Tab文字颜色
   tabSelectedTextColor      Tab被选中时文字的颜色
然后给ViewPager写一个简单的适配器
public class TabPageAdapter extends PagerAdapter {

    private List<ImageView> imageViews;
    private String[] titles;

    public TabPageAdapter(List<ImageView> imageViews, String[] titles) {
        this.imageViews = imageViews;
        this.titles = titles;
    }

    @Override
    public int getCount() {
        return imageViews.size();
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        container.addView(imageViews.get(position));
        return imageViews.get(position);
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView(imageViews.get(position));
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return titles[position];
    }
}
然后在MainActivity中写一下几行代码就可以实现效果
        //创建适配器
        TabPageAdapter adapter = new TabPageAdapter(imageViewList, titles);
        viewPager.setAdapter(adapter);
        //把ViewPager和TabLayout关联
        tabLayout.setupWithViewPager(viewPager);



setupWithViewPager()这个方法会在内部帮我们创建Tab添加到TabLayout,当然我们也可以手动自己添加
        for (int i = 0; i < 5; i++) {
            TabLayout.Tab tab = tabLayout.newTab();
            //为Tab设置文字
            tab.setText(titles[i]);
            //为Tab设置图标
            tab.setIcon(R.mipmap.ic_launcher);
            //为tab设置自定义显示布局
            //tab.setCustomView(customView);
            tabLayout.addTab(tab);
        }
        //创建适配器
        TabPageAdapter adapter = new TabPageAdapter(imageViewList, titles);
        viewPager.setAdapter(adapter);
        //设置Tab显示填满布局
        tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
        //设置Tab滚动模式为默认
        tabLayout.setTabMode(TabLayout.MODE_FIXED);
        //设置指示器高度
        tabLayout.setSelectedTabIndicatorHeight(10);
但这个时候我们就不能使用setupWithViewPager()来使TabLayout和ViewPager关联了,我们必须分别为ViewPager和TabLayout设置监听来实现关联
        tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                viewPager.setCurrentItem(tab.getPosition());
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {
<span style="white-space:pre">		</span>//当tab被重复选择时回调的方法
            }
        });
        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                //如果想要指示器随着ViewPager一起滑动就使用此方法
                //第三个参数设置为true,表示滑动后更新tab的选择状态
                //就不需要在onPageSelected中写代码了
                tabLayout.setScrollPosition(position, positionOffset, true);
            }

            @Override
            public void onPageSelected(int position) {
//                tabLayout.getTabAt(position).select();
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
那为什么自己添加tab后不能用setupWithViewPager()呢?我们先来看看源码
        public void setupWithViewPager(@NonNull ViewPager viewPager) {
        final PagerAdapter adapter = viewPager.getAdapter();
        if (adapter == null) {
            throw new IllegalArgumentException("ViewPager does not have a PagerAdapter set");
        }

        // First we'll add Tabs, using the adapter's page titles
        setTabsFromPagerAdapter(adapter);

        // Now we'll add our page change listener to the ViewPager
        viewPager.addOnPageChangeListener(new TabLayoutOnPageChangeListener(this));

        // Now we'll add a tab selected listener to set ViewPager's current item
        setOnTabSelectedListener(new ViewPagerOnTabSelectedListener(viewPager));

        // Make sure we reflect the currently set ViewPager item
        if (adapter.getCount() > 0) {
            final int curItem = viewPager.getCurrentItem();
            if (getSelectedTabPosition() != curItem) {
                selectTab(getTabAt(curItem));
            }
        }
    }

    public void setTabsFromPagerAdapter(@NonNull PagerAdapter adapter) {
        removeAllTabs();
        for (int i = 0, count = adapter.getCount(); i < count; i++) {
            addTab(newTab().setText(adapter.getPageTitle(i)));
        }
    }
这样原因就很明显了setupWithViewPager()中会调用setTabsFromPageAdapter()方法,而这个方法中会清空TabLayout中已经添加的Tab,然后再根据传入的适配器确定Tab的个数重新添加Tab和根据adapter中getPageTitle()设置Tab的标签。所以如果你为Tab设置的自定义View无法显示时,很有可能就是你在设置自定义View后误用了setupWithViewPager()或setTabsFromPageAdapter()方法。




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值