0%

[MaterialDesign] Android Tabs

Introduction

Material Design中,Tabs使用頁籤的方式管理不同的畫面,通常位於Toolbar的下方,常與Fragment/ViewPager搭配使用。背景的顏色通常也與Toolbar一致

在常見的使用中,Tabs可以被分為兩種模式
1.Fixed
Fixed模式下,每個Tab item的大小都是一致的,也因為大小都一樣,所以在設計上通常放置兩個(含)以上,最多四個item
2.Scrollable
Scrollable模式下,Tab item常為4個以上

Tabs item設計上,不管是Fixed模式或是Scrollable模式,都可以用文字 / 圖案 / 文字+圖案下去設計,接下來我們來實際創建一個Tabs + ViewPager

Create a Tab Layout with Text: Fixed Mode

添加support:design library

使用TabLayout,首先需要把support:design library添加進我們的Project中,在 File -> Project Structure -> Dependencles 下新增。

創建TabLayout

xml裡,創建一個TabLayout,賦予屬性app:tabMode=”fixed”,背景顏色使用跟Toolbar(colorPrimary)顏色一致,接著在下方創建ViewPager

app:tabGravity=”fill”表示tabs item會填滿整個TabLayout

layout:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">

<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:id="@+id/toolbar_id"
android:background="@color/colorPrimary"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>

<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/tabLayout_id"
android:layout_below="@+id/toolbar_id"
android:background="@color/colorPrimary"
app:tabMode="fixed"
app:tabGravity="fill"/>

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

</RelativeLayout>

預覽效果如下:

Define layouts for the items in TabLayout

我們新增Fragmentlayout,這些View,會顯示在ViewPager中,同時透過TabLayoutsetupWithViewPager()方法,能夠自動產生對應ViewPagerviewtab item

新增Fragment layout
layout:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v7.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/main_item_one"
android:textSize="60sp"
android:textStyle="bold"/>

</RelativeLayout>

預覽效果如下:

接著依序創建layout_item_twolayout_item_three_layout,總共3個layout

Create Java class for item layout

接下來創建Freagment class

java:

1
2
3
4
5
6
7
8
9
10
11
public class OneFragment extends Fragment {

private View view;

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.layout_item_one, container, false);
return view;
}
}

依序創建:
layout_item_one
layout_item_two
layout_item_three
Fragment class

Create a ViewPager Adapter

接下來我們創建ViewPagerAdapter,並繼承FragmentPagerAdapter

java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class ViewPagerAdapter extends FragmentPagerAdapter {

private List<Fragment> fragmentList = new ArrayList<>();
private List<String> fragmentTitleList = new ArrayList<>();

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

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

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

@Nullable
@Override
public CharSequence getPageTitle(int position) {
// 取得當前頁的title
return fragmentTitleList.get(position);
}

// 添加Fragment 與 Title 方法
public void addFragment(Fragment fragment, String title) {
fragmentList.add(fragment);
fragmentTitleList.add(title);
}
}

Setting TabLayout

Adapter創建完成之後,回到Activity,把Fragment加進adapter,並把它與ViewPager綁定

java:

1
2
3
4
5
6
7
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());

adapter.addFragment(new OneFragment(), "ITEM ONE");
adapter.addFragment(new TwoFragment(), "ITEM TWO");
adapter.addFragment(new ThreeFragment(), "ITEM THREE");

viewPager.setAdapter(adapter);

TabLayout有提供我們一個基於ViewPager快速創建對應Tabs的方法

java:

1
2
3
tabLayout = findViewById(R.id.tabLayout_id);

tabLayout.setupWithViewPager(viewPager);

運行效果如下:

改變Tab文字顏色,在TabLayouttag裡,添加屬性

1
app:tabTextColor="@color/colorWhite"

運行效果如下:

改變Tab被選中的文字顏色,在TabLayouttag裡,添加屬性

1
app:tabSelectedTextColor="@color/colorAccent"

運行效果如下:

改變TabLayout下方游標顏色,在TabLayouttag裡,添加屬性

1
app:tabIndicatorColor="@color/colorLightBlue"

運行效果如下:

改變TabLayout下方游標高度,在TabLayouttag裡,添加屬性

1
app:tabIndicatorHeight="10dp"

運行效果如下:

Create a Tab Layout with Text: Scrollable Mode

要創建可滑動的TabLayout,首先把屬性app:tabMode改為scrollable

1
app:tabMode="scrollable"
1
2
3
4
5
6
7
8
9
10
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/tabLayout_id"
android:layout_below="@+id/toolbar_id"
android:background="@color/colorPrimary"
app:tabMode="scrollable"
app:tabGravity="fill"
app:tabTextColor="@android:color/white"
app:tabSelectedTextColor="@color/colorAccent"/>

接著創建十個layout

創建十個Java Class

Activity裡添加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new OneFragment(), "ITEM ONE");
adapter.addFragment(new TwoFragment(), "ITEM TWO");
adapter.addFragment(new ThreeFragment(), "ITEM THREE");
adapter.addFragment(new FourFragment(), "ITEM FOUR");
adapter.addFragment(new FiveFragment(), "ITEM FIVE");
adapter.addFragment(new SixFragment(), "ITEM SIX");
adapter.addFragment(new SevenFragment(), "ITEM SEVEN");
adapter.addFragment(new EightFragment(), "ITEM EIGHT");
adapter.addFragment(new NineFragment(), "ITEM NINE");
adapter.addFragment(new TenFragment(), "ITEM TEN");
viewPager.setAdapter(adapter);

tabLayout.setupWithViewPager(viewPager);

運行效果如下:

Create a Tab Layout with Icon

接下來我們以Fixed Mode實現,在TabLayout頁籤裡,只顯示icon的效果

首先在XML裡,把app:tabMode設為**”fixed”**

1
2
3
4
5
6
7
8
9
10
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/tabLayout_id"
android:layout_below="@+id/toolbar_id"
android:background="@color/colorPrimary"
app:tabMode="fixed"
app:tabGravity="fill"
app:tabTextColor="@android:color/white"
app:tabSelectedTextColor="@color/colorAccent"/>

接著同樣新增3個Layout

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/recents"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:textSize="40sp"
android:textStyle="bold"/>

</RelativeLayout>

創建剛剛新增layoutjava class(Fragment)

1
2
3
4
5
6
7
8
9
10
11
12
13
public class RecentsFragment extends Fragment {

View view;

public RecentsFragment() {}

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.recents_layout,container,false);
return view;
}
}

創建ViewPagerAdapter,這邊我們沒有覆寫**getPageTitle()**方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class ViewPagerAdapter extends FragmentPagerAdapter {

private List<Fragment> fragmentList = new ArrayList<>();
private List<String> fragmentTitleList = new ArrayList<>();

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

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

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

// 添加Fragment 與 Title 方法
public void addFragment(Fragment fragment, String title) {
fragmentList.add(fragment);
fragmentTitleList.add(title);
}
}

Activity裡初始化,在綁定Adapter後,使用getTabAt()取得各項Tab後,設定各個icon

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class MainActivity extends AppCompatActivity {

Toolbar toolbar;
TabLayout tabLayout;
ViewPager viewPager;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = findViewById(R.id.toolbar_id);
setSupportActionBar(toolbar);

viewPager = findViewById(R.id.viewPager_id);
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new RecentsFragment(),"RECENTS");
adapter.addFragment(new FavoritesFragment(),"FAVORITES");
adapter.addFragment(new NearbyFragment(),"NEARBY");
viewPager.setAdapter(adapter);

tabLayout = findViewById(R.id.tabLayout_id);
tabLayout.setupWithViewPager(viewPager);
// 添加icon
tabLayout.getTabAt(0).setIcon(R.drawable.phone);
tabLayout.getTabAt(1).setIcon(R.drawable.heart);
tabLayout.getTabAt(2).setIcon(R.drawable.account);
}
}

運行效果如下:

Create a Tab Layout with Icon and Text

如果想要Tabs同時擁有圖片文字,只要在ViewPageAdapter裡,覆寫**getPageTitle()**方法就行了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class ViewPagerAdapter extends FragmentPagerAdapter {

private List<Fragment> fragmentList = new ArrayList<>();
private List<String> fragmentTitleList = new ArrayList<>();

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

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

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

@Nullable
@Override
public CharSequence getPageTitle(int position) {
// 取得當前頁的title
return fragmentTitleList.get(position);
}

// 添加Fragment 與 Title 方法
public void addFragment(Fragment fragment, String title) {
fragmentList.add(fragment);
fragmentTitleList.add(title);
}
}

運行效果如下:

Create a Tabs item with Java

不使用ViewPager,也可以透過代碼創建TabsItem

1
2
3
4
5
tabLayout = findViewById(R.id.tabLayout_id);

tabLayout.addTab(tabLayout.newTab().setText("RECENTS").setIcon(R.drawable.phone));
tabLayout.addTab(tabLayout.newTab().setText("FAVORITES").setIcon(R.drawable.heart));
tabLayout.addTab(tabLayout.newTab().setText("NEARBY").setIcon(R.drawable.account));

Create a Tabs item in XML

不使用ViewPager,在Layout.xml裡,創建TabItem

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/tabLayout_id"
android:layout_below="@+id/toolbar_id"
android:background="@color/colorPrimary"
app:tabMode="fixed"
app:tabGravity="fill">

<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/recents"
android:icon="@drawable/phone"/>

<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/favorites"
android:icon="@drawable/heart"/>

<android.support.design.widget.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/nearby"
android:icon="@drawable/account"/>

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

參考資料:
Android TabLayout
Material Design