Material Design 控件知識(shí)梳理(1) - Android Design Support Library 是什么
Material Design 控件知識(shí)梳理(2) - AppBarLayout & CollapsingToolbarLayout
Material Design 控件知識(shí)梳理(3) - BottomSheet && BottomSheetDialog && BottomSheetDialogFragment
Material Design 控件知識(shí)梳理(4) - FloatingActionButton
Material Design 控件知識(shí)梳理(5) - DrawerLayout && NavigationView
Material Design 控件知識(shí)梳理(6) - Snackbar
Material Design 控件知識(shí)梳理(7) - BottomNavigationBar
Material Design 控件知識(shí)梳理(8) - TabLayout
Material Design 控件知識(shí)梳理(9) - TextInputLayout
一、概述
前面我們介紹了BottomNavigationBar
,TabLayout
和它的作用類(lèi)似谋减,都是方便用戶(hù)進(jìn)行頁(yè)面之間的切換坚嗜。
二坏为、TabLayout
的基本用法
下面陨囊,我們先演示一遍TabLayout
的基本用法
第一步:引入依賴(lài):
compile 'com.android.support:design:25.3.1'
第二步:定義布局,這里使用了最常用的TabLayout+ViewPager
的結(jié)構(gòu):
<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
剧辐,這里需要重寫(xiě)getPageTitle
方法寒亥,它就對(duì)應(yīng)的是TabLayout
當(dāng)中的文案:
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
設(shè)置數(shù)據(jù),并把ViewPager
和TabLayout
關(guān)聯(lián)起來(lái):
public class TabLayoutActivity extends AppCompatActivity {
private static final String[] TITLE_SHORT = new String[] {
"深圳","南京","內(nèi)蒙古"
};
private static final String[] TITLE_LONG = new String[] {
"深圳","南京","內(nèi)蒙古呼和浩特","廣西壯族自治區(qū)","上海","北京","天津"
};
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
相關(guān)設(shè)置
3.1 TabItem
的外觀設(shè)置
對(duì)于每個(gè)TabItem
的外觀护盈,TabLayout
我們比較常用的屬性有:
- 未選中
TabItem
的文本顏色:app:tabTextColor
- 選中
TabItem
的文本顏色app:tabSelectedTextColor
- 底部滑動(dòng)條的顏色:
app:tabIndicatorColor
- 底部滑動(dòng)條的高度:
app:tabIndicatorHeight
-
TabItem
的背景:app:tabBackground
我們?cè)诘诙?jié)的基礎(chǔ)上進(jìn)行修改:
<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" />
最終展現(xiàn)的效果為:
3.2 TabItem
的寬高相關(guān)設(shè)置
有兩個(gè)關(guān)于寬度的屬性比較重要:tabMinWidth
和tabMaxWidth
,它允許我們這是每個(gè)TabItem
的最小和最大寬度羞酗。
此外腐宋,我們還可以設(shè)置TabItem
四個(gè)維度的Padding
。
3.3 tabMode
和tabGravity
上面只是決定了單個(gè)TabItem
的外觀檀轨,而TabItem
在TabLayout
當(dāng)中的擺放規(guī)則需要由這兩個(gè)屬性來(lái)決定胸竞,它們可選的值分別為:
-
tabMode
:fixed
或者scrollable
-
tabGravity
:fill
或者center
這兩個(gè)屬性分別通過(guò):app:tabMode
和app:tabGravity
來(lái)設(shè)置,下面参萄,我們就來(lái)解釋這幾個(gè)值的含義卫枝。
3.3.1 tabMode=fixed
在這種模式下,每個(gè)TabItem
的寬度都是相等的讹挎,并且所有的TabItem
加起來(lái)的寬度不會(huì)大于TabLayout
的寬度校赤,最終展現(xiàn)的結(jié)果還需要依賴(lài)于tabGravity
屬性:
-
tabGravity=fill
要求所有TabItem
加起來(lái)的寬度等于TabLayout
的寬度吆玖,也就是下面的效果
-
tabGravity=center
不要求TabItem
加起來(lái)的寬度等于TabLayout
的寬度,會(huì)根據(jù)每個(gè)TabItem
的屬性马篮,計(jì)算出TabItem
的寬度沾乘,然后取它們中的最大值乘上TabItem
的個(gè)數(shù),當(dāng)這一數(shù)值小于TabLayout
的寬度時(shí)浑测,會(huì)將每個(gè)TabItem
的寬度設(shè)置為這個(gè)最大值翅阵,并將它們放置在整個(gè)TabLayout
的中間,而如果這一數(shù)值大于TabLayout
的寬度迁央,那么會(huì)將它們?cè)?code>TabLayout中均勻排列掷匠。
3.3.2 tabMode=scrollable
在tabMode=fixed
模式下,TabItem
的位置是固定的岖圈,并且它們加起來(lái)的寬度不會(huì)大于TabLayout
的寬度讹语,而在scrollable
模式下則沒(méi)有這一限制,只需要計(jì)算好每個(gè)TabItem
的寬度蜂科,然后把它們排列在TabLayout
中就好了募强,可以通過(guò)拖動(dòng)的方式查看更多的TabItem
,并且當(dāng)tabMode=scrollable
時(shí)崇摄,tabGravity
其實(shí)并沒(méi)有作用,下面是tabMode=scrollable
的事例:
在這種模式下慌烧,每個(gè)
TabItem
的寬度默認(rèn)情況下是根據(jù)文字的寬度計(jì)算出來(lái)的逐抑,如果我們希望進(jìn)行相應(yīng)的限制,那么可以修改tabMinWidth
或者tabMaxWidth
屬性屹蚊。
3.4 設(shè)置監(jiān)聽(tīng)
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
厕氨,某個(gè)TabItem
從未選中狀態(tài)變?yōu)檫x中狀態(tài)時(shí)回調(diào) -
onTabUnselected
,某個(gè)TabItem
從選中變?yōu)槲催x中時(shí)回調(diào) -
onTabReselected
汹粤,某個(gè)TabItem
已經(jīng)處于選中狀態(tài)命斧,但是它又被再次點(diǎn)擊了,那么回調(diào)這個(gè)函數(shù)嘱兼。
四国葬、TabLayout + ViewPager
使用TabLayout
時(shí),一般都是采用ViewPager
來(lái)管理多個(gè)子界面芹壕,而TabLayout
也十分貼心地提供了方法讓它和ViewPager
的滾動(dòng)關(guān)聯(lián)起來(lái)汇四,當(dāng)點(diǎn)擊TabLayout
中的Item
時(shí),會(huì)切換到ViewPager
對(duì)應(yīng)的界面踢涌,而如果滑動(dòng)了ViewPager
通孽,那么TabLayout
也會(huì)切換到對(duì)應(yīng)的TabItem
。
我們所需要的只是下面這句設(shè)置:
mTabLayout.setupWithViewPager(mViewPager);
為了能讓TabLayout
知道TabItem
的標(biāo)題睁壁,需要重寫(xiě)ViewPager
所對(duì)應(yīng)的PagerAdapter
中getPageTitle
的方法:
@Override
public CharSequence getPageTitle(int position) {
return mTitles.get(position);
}
雖然TabLayout
并沒(méi)有提供切換到某個(gè)具體位置TabItem
的方法背苦,但是其實(shí)這一過(guò)程這完全可以通過(guò)mViewPager.setCurrentItem(int item)
來(lái)實(shí)現(xiàn)互捌。
更多文章,歡迎訪問(wèn)我的 Android 知識(shí)梳理系列:
- Android 知識(shí)梳理目錄:http://www.reibang.com/p/fd82d18994ce
- 個(gè)人主頁(yè):http://lizejun.cn
- 個(gè)人知識(shí)總結(jié)目錄:http://lizejun.cn/categories/