一、概述
前面我們介紹了BottomNavigationBar
,TabLayout
和它的作用類似,都是方便使用者進行頁面之間的切換。
二、TabLayout
的基本用法
下面,我們先演示一遍TabLayout
的基本用法
第一步:引入依賴:
compile 'com.android.support:design:25.3.1'
複製程式碼
第二步:定義佈局,這裡使用了最常用的TabLayout+ViewPager
的結構:
<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:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.demo.lizejun.repotransition.TabLayoutActivity">
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="scrollable"
app:tabGravity="center"/>
<android.support.v4.view.ViewPager
android:id="@+id/vp_content"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
複製程式碼
第三步:定義ViewPager
的Adapter
,這裡需要重寫getPageTitle
方法,它就對應的是TabLayout
當中的文案:
public class ViewPagerAdapter extends PagerAdapter {
private List<String> mTitles;
public ViewPagerAdapter(List<String> title) {
mTitles = title;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
ViewGroup itemView = (ViewGroup) LayoutInflater.from(container.getContext()).inflate(R.layout.item_view_pager, container, false);
container.addView(itemView);
TextView tv = (TextView) itemView.findViewById(R.id.tv_title);
tv.setText(mTitles.get(position));
return itemView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public int getCount() {
return mTitles.size();
}
@Override
public CharSequence getPageTitle(int position) {
return mTitles.get(position);
}
}
複製程式碼
第四步:給ViewPager
設定資料,並把ViewPager
和TabLayout
關聯起來:
public class TabLayoutActivity extends AppCompatActivity {
private static final String[] TITLE_SHORT = new String[] {
"深圳","南京","內蒙古"
};
private static final String[] TITLE_LONG = new String[] {
"深圳","南京","內蒙古呼和浩特","廣西壯族自治區","上海","北京","天津"
};
private ViewPager mViewPager;
private TabLayout mTabLayout;
private ViewPagerAdapter mViewPagerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tab_layout);
initViewPager();
initTabLayout();
}
private void initViewPager() {
mViewPager = (ViewPager) findViewById(R.id.vp_content);
List<String> titles = new ArrayList<>();
Collections.addAll(titles, TITLE_LONG);
mViewPagerAdapter = new ViewPagerAdapter(titles);
mViewPager.setAdapter(mViewPagerAdapter);
}
private void initTabLayout() {
mTabLayout = (TabLayout) findViewById(R.id.tab_layout);
mTabLayout.setupWithViewPager(mViewPager);
}
}
複製程式碼
最終的效果為:
三、TabLayout
相關設定
3.1 TabItem
的外觀設定
對於每個TabItem
的外觀,TabLayout
我們比較常用的屬性有:
- 未選中
TabItem
的文字顏色:app:tabTextColor
- 選中
TabItem
的文字顏色app:tabSelectedTextColor
- 底部滑動條的顏色:
app:tabIndicatorColor
- 底部滑動條的高度:
app:tabIndicatorHeight
TabItem
的背景:app:tabBackground
我們在第二節的基礎上進行修改:
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="scrollable"
app:tabGravity="center"
app:tabTextColor="@android:color/darker_gray"
app:tabSelectedTextColor="@android:color/holo_orange_dark"
app:tabIndicatorColor="@android:color/holo_orange_dark"
app:tabIndicatorHeight="2dp"
app:tabBackground="@android:color/transparent" />
複製程式碼
最終展現的效果為:
3.2 TabItem
的寬高相關設定
有兩個關於寬度的屬性比較重要:tabMinWidth
和tabMaxWidth
,它允許我們這是每個TabItem
的最小和最大寬度。
此外,我們還可以設定TabItem
四個維度的Padding
。
3.3 tabMode
和tabGravity
上面只是決定了單個TabItem
的外觀,而TabItem
在TabLayout
當中的擺放規則需要由這兩個屬性來決定,它們可選的值分別為:
tabMode
:fixed
或者scrollable
tabGravity
:fill
或者center
這兩個屬性分別通過:app:tabMode
和app:tabGravity
來設定,下面,我們就來解釋這幾個值的含義。
3.3.1 tabMode=fixed
在這種模式下,每個TabItem
的寬度都是相等的,並且所有的TabItem
加起來的寬度不會大於TabLayout
的寬度,最終展現的結果還需要依賴於tabGravity
屬性:
tabGravity=fill
要求所有TabItem
加起來的寬度等於TabLayout
的寬度,也就是下面的效果tabGravity=center
不要求TabItem
加起來的寬度等於TabLayout
的寬度,會根據每個TabItem
的屬性,計算出TabItem
的寬度,然後取它們中的最大值乘上TabItem
的個數,當這一數值小於TabLayout
的寬度時,會將每個TabItem
的寬度設定為這個最大值,並將它們放置在整個TabLayout
的中間,而如果這一數值大於TabLayout
的寬度,那麼會將它們在TabLayout
中均勻排列。
3.3.2 tabMode=scrollable
在tabMode=fixed
模式下,TabItem
的位置是固定的,並且它們加起來的寬度不會大於TabLayout
的寬度,而在scrollable
模式下則沒有這一限制,只需要計算好每個TabItem
的寬度,然後把它們排列在TabLayout
中就好了,可以通過拖動的方式檢視更多的TabItem
,並且當tabMode=scrollable
時,tabGravity
其實並沒有作用,下面是tabMode=scrollable
的事例:
TabItem
的寬度預設情況下是根據文字的寬度計算出來的,如果我們希望進行相應的限制,那麼可以修改tabMinWidth
或者tabMaxWidth
屬性。
3.4 設定監聽
mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
Log.d("onTabSelected", "position=" + tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
Log.d("onTabUnselected", "position=" + tab.getPosition());
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
Log.d("onTabReselected", "position=" + tab.getPosition());
}
});
複製程式碼
onTabSelected
,某個TabItem
從未選中狀態變為選中狀態時回撥onTabUnselected
,某個TabItem
從選中變為未選中時回撥onTabReselected
,某個TabItem
已經處於選中狀態,但是它又被再次點選了,那麼回撥這個函式。
四、TabLayout + ViewPager
使用TabLayout
時,一般都是採用ViewPager
來管理多個子介面,而TabLayout
也十分貼心地提供了方法讓它和ViewPager
的滾動關聯起來,當點選TabLayout
中的Item
時,會切換到ViewPager
對應的介面,而如果滑動了ViewPager
,那麼TabLayout
也會切換到對應的TabItem
。
我們所需要的只是下面這句設定:
mTabLayout.setupWithViewPager(mViewPager);
複製程式碼
為了能讓TabLayout
知道TabItem
的標題,需要重寫ViewPager
所對應的PagerAdapter
中getPageTitle
的方法:
@Override
public CharSequence getPageTitle(int position) {
return mTitles.get(position);
}
複製程式碼
雖然TabLayout
並沒有提供切換到某個具體位置TabItem
的方法,但是其實這一過程這完全可以通過mViewPager.setCurrentItem(int item)
來實現。
更多文章,歡迎訪問我的 Android 知識梳理系列:
- Android 知識梳理目錄:www.jianshu.com/p/fd82d1899…
- 個人主頁:lizejun.cn
- 個人知識總結目錄:lizejun.cn/categories/