谷歌TabLayout及FlycoTabLayout三方庫入門
一、簡介
谷歌在 2014 年 I/O 大會上重磅推出了一套全新的介面設計語言 Material Design ,用於解決 Android 平臺介面風格不統一的問題,並且親力親為從 Android 5.0 系統開始將自家所有內建應用統一使用 Material Design 風格進行設計。
但由於缺少相關 API 支援,作為開發者實現起來難度較大。於是,谷歌在 2015 年 I/O 大會上又推出了 Design Support 庫,將最具代表性的控制元件和效果進行了封裝,使得開發者在即使不瞭解 Material Design 的情況下也能輕鬆將自己的應用 Material 化。TabLayout 便是 Design Support 庫中的一個全新控制元件。
TabLayout 允許開發者將標籤指示器(Tab)與其對應的頁面(一般為ViewPager)進行關聯,達到切換標籤指示器的同時,與它關聯的頁面也會跟著一起滑動的效果。如下圖所示:

TabLayout + ViewPager + Fragment
二、TabLaout 單獨使用
- 因為 TabLaout 位於 Design Support 庫中,所以想要使用 TabLaout ,第一步便是在 app 的 build gradle 中引入 Design Support 庫:
dependencies { ...... implementation 'com.android.support:design:28.0.0-rc02' }
- 編寫 xml 佈局:
<?xml version="1.0" encoding="utf-8"?> <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:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <!--tabIndicatorColor:指示器的顏色--> <!--tabIndicatorHeight:指示器的高度,可設定為0,相當於沒有指示器--> <!--tabTextColor:Tab未選中時字型的顏色--> <!--tabSelectedTextColor:Tab選中時字型的顏色--> <!--tabTextAppearance:Tab內文字的樣式,TabLayout沒有提供直接屬性設定文字大小,需通過該屬性指定style樣式從而改變文字大小--> <!--tabMode:Tab的顯示模式,預設為fixed(固定不能滑動,標籤很多時會被擠壓),可設定為scrollable(標籤很多時可向左滑動)--> <!--tabGravity:內容的顯示模式,可選center(居中)和fill(填充)--> <android.support.design.widget.TabLayout android:id="@+id/tl_main" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:tabIndicatorColor="@color/colorPrimaryDark" app:tabIndicatorHeight="3dp" app:tabTextColor="@android:color/black" app:tabSelectedTextColor="@color/colorPrimaryDark"> </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 = findViewById(R.id.tl_main); addTabToTabLayout(); } /** * Description:給TabLayout新增tab,Tab.setIcon()方法可以給Tab新增圖片 */ private void addTabToTabLayout() { String []mTitles = {"未支付賬單", "支付中賬單", "歷史賬單"}; for (int i = 0; i < mTitles.length; i++) { mTabLayout.addTab(mTabLayout.newTab().setText(mTitles[i])); //mTabLayout.addTab(mTabLayout.newTab().setText(mTitles[i]).setIcon(R.mipmap.ic_launcher)); } } }
效果圖如下:

未使用 setIcon() 的 Tab

使用了 setIcon() 的 Tab
-
注意:
TabLayout 沒有直接提供設定 Tab 內字型大小的屬性,需要通過 styles.xml 檔案自定義一個 style 樣式設定給 tabTextAppearance ,從而達到改變字型大小的目的。程式碼如下圖所示:
<android.support.design.widget.TabLayout ...... app:tabTextAppearance="@style/MyTabLayoutTextAppearance"> </android.support.design.widget.TabLayout>
對應的 style 程式碼如下所示:
<!--設定TabLayout內文字的字型大小--> <style name="MyTabLayoutTextAppearance"> <item name="android:textSize">18sp</item> </style>
另外,當 TabLayout 的 tabMode 設定為 fixed 時,如果字型大小設定過大,會導致 Tab 顯示異常,如下圖:

Tab顯示異常
解決辦法可以通過適當縮減字型大小或者設定 tabMode 為 scrollable 。
三、TabLayout 結合 ViewPager 與 Fragment
TabLayout 單獨使用的場景很少,它真正的強大之處在於可以結合 ViewPager 與 Fragment 共同使用,編寫出精美的可滑動頁面,常見於各種新聞、視訊客戶端。所以接下來就開始學習 TabLayout + ViewPager + Fragment 的使用吧。
-
編寫 xml 佈局:
在 TabLayout 下面放入一個 ViewPager 作為 Fragment 的容器。
<?xml version="1.0" encoding="utf-8"?> <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:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <android.support.design.widget.TabLayout android:id="@+id/tl_main" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:tabIndicatorColor="@color/colorPrimaryDark" app:tabIndicatorHeight="3dp" app:tabTextColor="@android:color/black" app:tabSelectedTextColor="@color/colorPrimaryDark"> </android.support.design.widget.TabLayout> <android.support.v4.view.ViewPager android:id="@+id/vp_main" android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v4.view.ViewPager> </LinearLayout>
-
編寫對應 Java 程式碼:
先上 Activity 程式碼,較為簡單,不做過多解釋。
public class MainActivity extends AppCompatActivity { private TabLayout mTabLayout; private String [] mTitles = {"未支付賬單", "支付中賬單", "歷史賬單"}; private MyFragmentPagerAdapter mAdapter; private ViewPager mViewPager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTabLayout = findViewById(R.id.tl_main); mViewPager = findViewById(R.id.vp_main); addTabToTabLayout(); setupWithViewPager(); } /** * Description:給TabLayout新增tab */ private void addTabToTabLayout() { for (int i = 0; i < mTitles.length; i++) { mTabLayout.addTab(mTabLayout.newTab().setText(mTitles[i])); } } /** * Description:初始化FragmentPagerAdapter介面卡並給ViewPager設定上該介面卡,最後關聯TabLayout和ViewPager */ private void setupWithViewPager() { List<Fragment> mFragments = new ArrayList<>(); mFragments.add(new FirstFragment()); mFragments.add(new SecondFragment()); mFragments.add(new ThirdFragment()); mAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager()); mAdapter.addTitlesAndFragments(mTitles, mFragments); mViewPager.setAdapter(mAdapter); // 給ViewPager設定介面卡 mTabLayout.setupWithViewPager(mViewPager); //關聯TabLayout和ViewPager } }
然後是 ViewPager 的介面卡程式碼。
public class MyFragmentPagerAdapter extends FragmentPagerAdapter { private String []titles; private List<Fragment> fragments; public MyFragmentPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int i) { return fragments.get(i); } @Override public int getCount() { return titles.length; } @Nullable @Override public CharSequence getPageTitle(int position) { return titles[position]; } //自定義一個新增title和fragment的方法,供Activity使用 public void addTitlesAndFragments(String []titles, List<Fragment> fragments) { this.titles = titles; this.fragments = fragments; } }
最後是 Fragment 程式碼,較為簡單,這裡只貼出三個 Fragment 中的一個,對應的佈局請隨意,略過。
public class FirstFragment extends Fragment { @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View mView = inflater.inflate(R.layout.layout_fragment_first, null); return mView; } }
最終效果圖如下:

TabLayout + ViewPager + Fragment
四、TabLayout 第三方庫 —— FlycoTabLayout
有時候官方 TabLayout 並不能滿足實際開發需求,如想要改變 TabLayout 指示器的寬度,甚至設定指示器寬度和 Tab 內文字寬度一致,就會很麻煩,需要通過反射拿到 TabLayout 內的 TextView 物件並測量其寬度,最後通過 LayoutParams 設定給 TabLayout 。所以,各種第三方 TabLayout 庫應運而生。
這裡本人種草一波 FlycoTabLayout 庫,該庫集成了三種 TabLayout ,不同場景和需求下使用不同的庫,可以高效且優雅地完成開發中各種五花八門的需求。該庫功能強大,使用起來卻又相當簡單,你甚至不需要寫 ViewPager 的介面卡,僅一行程式碼就能關聯 TabLayout 和 ViewPager 。想了解更多關於該庫的介紹可以移步 github ,附上 github 地址:
ofollow,noindex">https://github.com/H07000223/FlycoTabLayout
話不多說,接下來開始實踐。
- 在 app 的 build gradle 中引入 FlycoTabLayout 庫:
dependencies { ...... implementation 'com.flyco.tablayout:FlycoTabLayout_Lib:2.1.2@aar' }
-
編寫 xml 佈局:
這裡我使用了 FlycoTabLayout 庫其中的 SlidingTabLayout ,實現 Tab 內指示器寬度與文字寬度一樣的效果。
同時可以看出,SlidingTabLayout 提供了專門的屬性設定文字的字型大小,不用再像使用 TabLayout 時編寫 style 屬性了。
<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:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <!--tl_indicator_color:指示器的顏色--> <!--tl_indicator_height:指示器的高度--> <!--tl_indicator_width:指示器的寬度--> <!--tl_textUnselectColor:Tab未選中時字型的顏色--> <!--tl_textSelectColor:Tab選中時字型的顏色--> <!--tl_textsize:字型大小--> <!--tl_indicator_width_equal_title:設定指示器寬度與文字寬度一致--> <!--tl_tab_space_equal:設定Tab大小等分--> <!--tl_divider_color:分割線的顏色--> <!--tl_divider_width:分割線的寬度--> <com.flyco.tablayout.SlidingTabLayout android:id="@+id/stl_main" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:tl_indicator_color="@color/colorPrimaryDark" app:tl_indicator_height="3dp" app:tl_textUnselectColor="@android:color/black" app:tl_textSelectColor="@color/colorPrimaryDark" app:tl_textsize="18sp" app:tl_indicator_width_equal_title="true" app:tl_tab_space_equal="true" app:tl_divider_color="@color/colorAccent" app:tl_divider_width="1dp"> </com.flyco.tablayout.SlidingTabLayout> <android.support.v4.view.ViewPager android:id="@+id/vp_main" android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v4.view.ViewPager> </LinearLayout>
-
編寫 Java 程式碼:
在 Activity 內的使用就更簡單了,真正實現一行程式碼解決問題,專治懶癌晚期患者。
public class MainActivity extends AppCompatActivity { private ViewPager mViewPager; private SlidingTabLayout slidingTabLayout; private ArrayList<Fragment> mFragments;; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); slidingTabLayout = findViewById(R.id.stl_main); mViewPager = findViewById(R.id.vp_main); mFragments = new ArrayList<>(); mFragments.add(new FirstFragment()); mFragments.add(new SecondFragment()); mFragments.add(new ThirdFragment()); //無需編寫介面卡,一行程式碼關聯TabLayout與ViewPager slidingTabLayout.setViewPager(mViewPager, new String[]{"未支付賬單", "支付中賬單", "歷史賬單"}, this, mFragments); } }
-
最終效果:
SlidingTabLayout實現指示器與文字寬度一致
至此,關於 TabLayout 與 SlidingTabLayout 的簡單使用就結束了。撒花!