Material Design Pattern (7) - TabLayout

使用 TabLayout 的方法很簡單。

<android.support.design.widget.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabMode="fixed"
        />

<TextView
        android:id="@+id/tv_name"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

activity.onCreate()

TabLayout tabLayout = (TabLayout)findViewById(R.id.tab_layout);
tabLayout.addTab(tabLayout.newTab().setText("TAB 1"));
tabLayout.addTab(tabLayout.newTab().setText("Tab 2"));
tabLayout.addTab(tabLayout.newTab().setText("Tab 3"));
tabLayout.addTab(tabLayout.newTab().setText("Tab 4"));
tabLayout.addTab(tabLayout.newTab().setText("Tab 5"));

tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
    @Override
    public void onTabSelected(TabLayout.Tab tab) {
        textView.setText(tab.getText());
    }

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

    }

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

    }
});

這樣轉 tab 時,TextView 會跟著變動。這是透過使用 TabLayoutOnTabSelectedListener 去做成一個 tab Activity。但我們通常會使用 TabLayout + ViewPager 去做,這樣彈性較大,也較方便。

TabLayout + ViewPager

ViewPager 是類似換頁的 place holder ,可以根據手勢 gesture 去切換頁面,顯示不同的 fragment。透過 ViewPager 和 TabLayout 的結合,可以更有效的扮演 tab 顯示。

ViewPager 需要一個 FragmentPagerAdapter 去運作,FragmentPagerAdapter 負責提供「內容」給 viewPager

public class TabPagerAdapter extends FragmentPagerAdapter {
    private static final int PAGE_COUNT = 5;

    public TabPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        return TabFragment.newInstance("Fragment tab", "No. "+ position);
    }

    @Override
    public int getCount() {
        return PAGE_COUNT;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return "Tab " + position;
    }
}

為示範, TabFragment 即只是一個簡單的 fragment

之後將 ViewPagerTabPagerAdapter 給合在一起:

ViewPager viewPager = (ViewPager)findViewById(R.id.viewpager);
viewPager.setAdapter(new TabPagerAdapter(getSupportFragmentManager()));

在 Layout 上加上 ViewPager

<android.support.design.widget.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabMode="scrollable"
        />

<android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="0px"
        android:layout_weight="1"
        />

此時 TabLayoutviewPager 是兩個個體,要將他們連結便要:

TabLayout tabLayout = (TabLayout)findViewById(R.id.tab_layout);
tabLayout.setupWithViewPager(viewPager);

這樣便完成了:

TabLayout demo result

tabMode

TabLayouttabMode 可以是 fixedscrollable

  • fixed 是全部 tab 顯示出來,
  • scrollable 即可以滑動顯示。

為標題加上 icon

可以在 TabPagerAdapter.getPageTitle() 做手腳,使用 SpannableString 為標題加上 icon (或其他格式)。

@Override
public CharSequence getPageTitle(int position) {
    Drawable icon = context.getResources().getDrawable(R.drawable.ic_add_circle_outline_white);
    icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
    ImageSpan iconSpan = new ImageSpan(icon, ImageSpan.ALIGN_BOTTOM);

    SpannableString sb = new SpannableString("  " + "Tab  " + position);
    sb.setSpan(iconSpan, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

    return sb;
}

但因為 TabLayout 本身的標題 style 設定了 texAllCaps ,令 SpannableString 失效,所以要先自行 disable 它。

<style name="MyTabTextAppearance" parent="TextAppearance.Design.Tab">
    <item name="textAllCaps">false</item>
</style>


<android.support.design.widget.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabMode="scrollable"
        app:tabTextAppearance="@style/MyTabTextAppearance"
        />

更新 style 後便可以顯示 icon 了。

Tab name with icon

其他 library - ViewPagerIndicator

除了使用 tabLayout ,其實還可使用歷史悠久的 ViewPagerIndicator,它提供更多顯示設定和類型。

![ViewPagerIndicator](/content/images/2016/03/viewpagerindicator.png)
不同款式 (source: ViewPagerIndicator 網站)

雖然很久沒有更新,但只是因為它功能已經非常完善。

不過因為作者沒有將 viewPagerIndicator 放佈到 gradle 上,所以要以以下方式安裝

repositories {
    maven { url "http://dl.bintray.com/populov/maven" }
    mavenCentral()
    // or jcenter()
}

dependencies {
    // ...
    compile 'com.viewpagerindicator:library:2.4.1@aar'
    // ...
}

使用方法跟 tabLayout 差不多,不另述了,可看行參看 source code。個人習慣使用 ViewPagerIndicator 較多。

Source code:

https://github.com/goofyz/android-material-design-tutorial/tree/part7_tablayout

相關連結:

  1. TabLayout - Google 官方 API 文件
  2. Google Play Style Tabs using TabLayout
  3. ViewPagerIndicator
  4. Using ViewPagerIndicator library with Android Studio and Gradle