TabLayout-Design Library

轉載請註明出處:https://medium.com/@devwilly,違者必究

圖片資料均屬原公司所有

由於工作上的關係會需要使用Tab相關元件,這讓我想起以前使用Tab時的痛苦回憶,上一次使用Tab的時間我已經想不起來了,約略只對TabHost有些印象。

當然GitHub上有幾套相當有名的third party library,這邊就不多做介紹了。Google在2015年的IO大會上,帶給大家更詳細的Material Design設計規範並導入全新的Android Design Support Library,在support library中Google提供了更符合MD規範的元件,更重要的是Design Support Library向下相容到Android 2.2。

How to use TabLayout ?

首先必需先把Design Support Library 加入專案中,將程式碼加入專案內App目錄下build.gradle中。

dependencies {
....
compile 'com.android.support:design:25.1.1'
}

接著再相對應的layout頁面中加入TabLayoutViewPager元件,若想客製化TabLayout可以利用style方式來改寫屬性。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent">

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


<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/tabs_layout"/>
</RelativeLayout>

自定義TabLayout樣式

要自定樣式前需了解TabLayout有哪些能控制的屬性,下圖為TabLayout預設提供的樣式。

TabLayout 預設樣式
tabTextAppearance 預設樣式
tabIndicatorColor: 指標顏色
tabIndicatorHeight: 指標高度
tabBackground: 背景顏色
tabTextAppearance:字體相關設定

以下範例是針對上述四點進行改寫(overwrite),效果如下圖

<style name="MyTabLayout" parent="Widget.Design.TabLayout">
<item name="tabBackground">#3F51B5</item>
<item name="tabIndicatorHeight">5dp</item>
<item name="tabIndicatorColor">#ff00ff</item>
<item name="tabSelectedTextColor">#ffffff</item>
<item name="tabTextAppearance">@style/MyTextAppearance</item>
</style>

<style name="MyTextAppearance" parent="TextAppearance.Design.Tab">
<item name="android:textSize">16sp</item>
<item name="android:textColor">#dbdbdb</item>
</style>
自定義TabLayout樣式

建立ViewPager 專屬Adapter

Adapter繼承分成 FragmentPagerAdapterFragmentStatePagerAdapter 兩種,最主要的差異就是沒使用的頁面資源是否會被回收。

FragmentPagerAdapter:頁面不會被回收,適合用於靜態頁面中。
FragmentStatePagerAdapter:沒使用的頁面會被回收,較適合用於多頁面。

這邊使用了Enum小技巧讓程式碼看起來簡潔(咦),不讓程式碼中出現一大堆getResource().getString(R.string.xxx)

public enum MovieType {
Week("本週新片", Fragment1.class.getName()),
ComingSoon("即將上映", Fragment2.class.getName()),
TOP("排行榜", Fragment3.class.getName());

private String mTitle;
private String mFragmentName;

MovieType(String title, String fragmentName) {
this.mTitle = title;
this.mFragmentName = fragmentName;
}

public String getTitle() {
return mTitle;
}

public String getFragmentName() {
return mFragmentName;
}
}

利用Enum將許多重複性的程式碼包起來,那要如何取得相對的標題名稱呢?

MovieMode.Week.getTitle()
MovieMode.ComingSoon.getTitle()
MovieMode.LeaderBoard.getTitle()

接著Adapter內需要放哪些資料呢?

  • getCount():Return the number of views available
  • getPageTitle(int position):取得相對的tab position標題
  • getItem(int position):每一個position對應到自己的Fragment page
public class MainTabAdapter extends FragmentPagerAdapter {


private MovieMode mTabTitle[] =
new MovieMode[]{Week, ComingSoon, TOP};

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

@Override
public Fragment getItem(int position) {
return MovieListFragment.newInstance(mTabTitle[position]);
}

@Override
public int getCount() {
return mTabTitle.length;
}

@Override
public CharSequence getPageTitle(int position) {
return mTabTitle[position].getTitle();
}
}

KeyPoint

附上幾個開發時碰到較為麻煩的問題,希望大家別再踩到地雷!!

(1) 避免使用Fragment in Fragment,因為lifecycle會讓你處理到崩潰XD

(2) 注意getSupportFragmentManager() getChildFragmentManager()的 使用時機,不然會造成Fragment被堆疊再FragmentManager中無法被釋放。

  • Fragment parent是Activity 請使用getSupportFragmentManager()
  • Fragment parent是Fragment 請使用getChildFragmentManager()

(3) FragmentPagerAdapter call notifyDataSetChanged() 是無法再次觸發adapter中的getItem(int position)

(4)FragmentStatePagerAdapter call notifyDataSetChanged() 會依據getItemPosition(Object object) 回傳的值來決定是否觸發getItem(int position)

  • POSITION_NONE:trigger getItem method
  • POSITION_UNCHANGED:non-trigger getItem method

Conclusion

Design Support Library 能快速實作符合MD規範的功能,讓我們省去許多調整時間,但並非所有功能都必須靠它完成,有時候反而會多此一舉。

最後附上Sample Code

若你喜歡這篇文章歡迎推薦給你的朋友
若你喜歡我的部落格歡迎追隨我
https://play.google.com/store/apps/details?id=com.devwilly.tutorial.tablayoutex

Reference

轉載請註明出處:https://medium.com/@devwilly,違者必究