Material Design 笔记之 TabLayout

Material Design 笔记之 TabLayout

标签: MaterialDesign


先上图

先看看

添加依赖

compile 'com.android.support:design:25.0.1'     //后面25.0.1是版本号,根据你的编译目标版本修改版本号

基本写法

  • XML
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"     <!-- 因为应用到第三方属性,需要命名属性空间 -->
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.zp.usetablayout.MainActivity">

    <android.support.design.widget.TabLayout        
            android:id="@+id/tablayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >

    </android.support.design.widget.TabLayout>

</LinearLayout>
  • Java
public class MainActivity extends AppCompatActivity {

    private TabLayout mTabLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTabLayout = ((TabLayout) findViewById(R.id.tablayout));    //找到控件

        //自身添加标签,自身new一个标签设置文本,传给自身
        mTabLayout.addTab(mTabLayout.newTab().setText("首页"));
        mTabLayout.addTab(mTabLayout.newTab().setText("个性化推荐"));
        mTabLayout.addTab(mTabLayout.newTab().setText("歌单"));
        mTabLayout.addTab(mTabLayout.newTab().setText("主播电台"));
        mTabLayout.addTab(mTabLayout.newTab().setText("排行榜"));
        mTabLayout.addTab(mTabLayout.newTab().setText("我的"));
    }

}

Tips:TabLayout可以在Java代码中设置Tab,也可以在XML布局中设置

  • 修改XML
    <android.support.design.widget.TabLayout
        android:id="@+id/tablayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabIndicatorColor="@color/colorPrimary"
        app:tabSelectedTextColor="@color/colorPrimary"
        app:tabTextColor="@android:color/darker_gray">
        <android.support.design.widget.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="首页"/>
        <android.support.design.widget.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="个性化推荐"/>
        <android.support.design.widget.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="歌单"/>
        <android.support.design.widget.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="主播电台"/>
        <android.support.design.widget.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="排行榜"/>
        <android.support.design.widget.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="我的"/>
    </android.support.design.widget.TabLayout>

Tips:同样的,如果想设置每个Tab带图片,在XML中android:icon="@drawable/ic_favorite_border_black_24dp",在Java代码中就是在setText之后再去setIcon()

基本写法就写完了,但是并不够啊,因为实际项目中不会这么粗简,既然如此,那就进阶吧

进阶

  • 了解实际需求

    在实际项目中,我们的需求更复杂一些,比如:需要改变Tabs指示器的高和颜色,需要改变Tab的宽高,选定的Tab颜色,滚动模式,更常用的Tabs+ViewPager+Fragment的配套使用等等

  • XML属性值说明

  • app:tabBackground 设置Tabs的背景
  • app:tabGravity 为Tabs设置Gravity,有两个常量值,GRAVITY_CENTER,GRAVITY_FILL,用法:
    app:tabGravity="center"
    或者
    app:tabGravity="fill"
    值为center,Tabs就居中显示,fill就充满TabLayout
  • app:tabIndicatorColor 设置指示器的颜色(默认颜色为colorAccent)
  • app:tabIndicatorHeight 设置指示器的高度,官方规范建议是2dp
  • app:tabMaxWidth 设置Tab的最大宽度
  • app:tabMinWidth 设置Tab的最小宽度
  • app:tabMode 设置Tabs的显示模式,有两个常量值,MODE_FIXED,MODE_SCROLLABLE。用法:
    app:tabMode="fixed"
    或者
    app:tabMode="scrollable"
    fixed表示固定的Tab,scrollable可滚动的Tab,Tab个数少的时候用fixed,当Tab个数较多时用scrollable。
  • app:tabPadding 很好理解,就是设置Tab的padding,下面同解
  • app:tabPaddingTop
  • app:tabPaddingBottom
  • app:tabPaddingStart
  • app:tabPaddingEnd
  • app:tabSelectedTextColor 设置Tab选中之后,文本显示的颜色
  • app:tabTextColor 设置Tab未选中时,文本显示的颜色
  • 实现TabLayout与ViewPager的联动

实现联动的关键有两点

  • mTabLayout.setupWithViewPager(mViewPager) 将TabLayout与ViewPager进行绑定
  • FragmentStatePagerAdapter V4包下作用于TabLayout和ViewPager的适配

1.修改XML中的布局

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.zp.usetablayout.MainActivity">

    <android.support.design.widget.TabLayout
        android:id="@+id/tablayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabBackground="@color/colorPrimary"
        app:tabIndicatorColor="@android:color/holo_red_light"       <!-- 指示器颜色 -->
        app:tabIndicatorHeight="2dp"                                <!-- 指示器高度 -->
        app:tabSelectedTextColor="@android:color/holo_red_light"    <!-- 选中的文本颜色 -->
        app:tabTextColor="@android:color/white">                    <!-- 未选中的文本颜色 -->

    </android.support.design.widget.TabLayout>

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

2.创建几个Fragment,数量取决你ViewPager想有几个界面,并设置不同的背景颜色以区分,我就创建6个Fragment了

public class MainActivity extends AppCompatActivity implements TabLayout.OnTabSelectedListener, ViewPager.OnPageChangeListener {

    private static final String TAG = "MainActivity";

    private TabLayout mTabLayout;
    private ViewPager mViewPager;

    private String[] tabName = new String[]{"首页", "个性化推荐", "歌单", "主播电台", "排行榜", "我"};
    //这两个集合到时候都要传到适配器里面去的
    private List<String> titles = new ArrayList<>();
    private List<Fragment> fragments = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTabLayout = ((TabLayout) findViewById(R.id.tablayout));
        mViewPager = ((ViewPager) findViewById(R.id.vp));

        initView();
    }

    private void initView() {
        for (int i = 0; i < tabName.length; i++) {
            //这个不用说,赋值到tab标签
            mTabLayout.addTab(mTabLayout.newTab().setText(tabName[i]));
            //赋值到集合中去
            titles.add(tabName[i]);
        }
        //添加标签选择监听
        mTabLayout.addOnTabSelectedListener(this);
        //实例化Fragment实例传入集合中去,此时上面说的两个集合都有数据了
        fragments.add(new HomeFragment());
        fragments.add(new RecomFragment());
        fragments.add(new MusicMenuFragment());
        fragments.add(new RadioFragment());
        fragments.add(new NoticeFragment());
        fragments.add(new MyFragment());

        //关键点---FragmentStatePagerAdapter的子类实例化
        MyFragmentAdapter adapter = new MyFragmentAdapter(getSupportFragmentManager(),fragments, titles);
        //给ViewPager设置适配器
        mViewPager.setAdapter(adapter);

        //给ViewPager设置页面改变监听
        mViewPager.addOnPageChangeListener(this);
        //关键点---将TabLayout与ViewPager进行绑定
        mTabLayout.setupWithViewPager(mViewPager);
    }

    @Override
    public void onTabSelected(TabLayout.Tab tab) {
        Log.i(TAG, "onTabSelected: " + tab.getText());
    }

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

    }

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

    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
        Log.i(TAG, "onPageSelected: " + titles.get(position));
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }
}

3.适配器(这可是关键)

public class MyFragmentAdapter extends FragmentStatePagerAdapter {
    private List<Fragment> mFragments ;
    private List<String> mTitles ;

    //第一个参数碎片管理器,第二个和第三个参数就不说了
    public MyFragmentAdapter(FragmentManager fm,List<Fragment> fragments,List<String> titles) {
        super(fm);
        mFragments = fragments;
        mTitles = titles;
    }

    @Override
    public Fragment getItem(int position) {
        return mFragments.get(position);
    }

    @Override
    public int getCount() {
        return mFragments == null ?0:mFragments.size();
    }

    /**
    * 这个函数就是给TabLayout的Tab设定Title
    */
    @Override
    public CharSequence getPageTitle(int position) {
        return mTitles.get(position);
    }
}

Tips:有人就问了,适配器里面的getPageTitle是给TabLayout的Tab设定Title,那我MainActivity可以不写mTabLayout.addTab(mTabLayout.newTab());吗?回答是:可以的;那我们将前面的这些代码注释掉,
此时MainActivity代码如下:

public class MainActivity extends AppCompatActivity implements TabLayout.OnTabSelectedListener, ViewPager.OnPageChangeListener {

    private static final String TAG = "MainActivity";

    private TabLayout mTabLayout;
    private ViewPager mViewPager;

    private String[] tabName = new String[]{"首页", "个性化推荐", "歌单", "主播电台", "排行榜", "我"};
    private List<String> titles = new ArrayList<>();
    private List<Fragment> fragments = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTabLayout = ((TabLayout) findViewById(R.id.tablayout));
        mViewPager = ((ViewPager) findViewById(R.id.vp));

        initView();
    }

    private void initView() {
        for (int i = 0; i < tabName.length; i++) {
//            mTabLayout.addTab(mTabLayout.newTab());           //这一行代码已经注视掉了
            titles.add(tabName[i]);
        }

        mTabLayout.addOnTabSelectedListener(this);

        fragments.add(new HomeFragment());
        fragments.add(new RecomFragment());
        fragments.add(new MusicMenuFragment());
        fragments.add(new RadioFragment());
        fragments.add(new NoticeFragment());
        fragments.add(new MyFragment());

        MyFragmentAdapter adapter = new MyFragmentAdapter(getSupportFragmentManager(),fragments, titles);

        mViewPager.setAdapter(adapter);

        mViewPager.addOnPageChangeListener(this);

        mTabLayout.setupWithViewPager(mViewPager);
    }

    @Override
    public void onTabSelected(TabLayout.Tab tab) {
        Log.i(TAG, "onTabSelected: " + tab.getText());
    }

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

    }

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

    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
        Log.i(TAG, "onPageSelected: " + titles.get(position));
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }
}

另一种方式:实现以上TabLayout与ViewPager的联动还有一种方式,其实也就是省略setupWithViewPager这一步的绑定,那到底是如何省略的?修改XML布局


    ···原谅我省略一些代码

    <android.support.v4.view.ViewPager
        android:id="@+id/vp"
        android:layout_below="@id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.design.widget.TabLayout
            android:id="@+id/tablayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabBackground="@color/colorPrimary"
            app:tabGravity="fill"
            app:tabIndicatorColor="@android:color/holo_red_light"
            app:tabIndicatorHeight="2dp"
            app:tabSelectedTextColor="@android:color/holo_red_light"
            app:tabTextColor="@android:color/white">

        </android.support.design.widget.TabLayout>
    </android.support.v4.view.ViewPager>

Tips:也就是将TabLayout作为ViewPager的子类,TabLayout会检查他的父类是不是ViewPager,是的话自动完成绑定(内部调用setupWithViewPager

结尾留点小问题

  • 适配器的这个函数应该还记得吧
    /**
    * 这个函数就是给TabLayout的Tab设定Title
    */
    @Override
    public CharSequence getPageTitle(int position) {
        return mTitles.get(position);
    }

这个函数返回的是一个字符串,这样的话就不能为Tab设置图标,但说实话我也不懂怎么解决,对这个问题有兴趣的人可以走进传送门,粗略看了一下说用SpannableString,具体不懂,懂的人记得告诉我一声;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值