前言
Tablayout繼承自HorizontalScrollView,用作頁(yè)面切換指示器掀亩,因使用簡(jiǎn)便功能強(qiáng)大而廣泛使用在App中舔哪。
但有的產(chǎn)品經(jīng)理偏偏是個(gè)磨人的小妖精,真的猜不透啊槽棍,今天要這種效果捉蚤,明天就指著另一款A(yù)pp說(shuō)做成跟這個(gè)一樣抬驴。對(duì)付這種產(chǎn)品經(jīng)理我們有骨氣的程序員該怎么辦?怎么辦缆巧?當(dāng)然是屈服啊布持,不然去跳樓讓他因內(nèi)疚改需求?
所以陕悬,就在各種復(fù)雜的情況下打磨题暖,漸漸地就變得圓潤(rùn)。這里捉超,有Tablayout的各種使用場(chǎng)景胧卤,拿去指著產(chǎn)品經(jīng)理說(shuō):你要哪個(gè)給你哪個(gè)。
先上效果圖:分別為設(shè)置tab屬性拼岳、去掉指示線(xiàn)枝誊、設(shè)置指示線(xiàn)長(zhǎng)度、設(shè)置圖標(biāo)tab惜纸、超出屏幕滾動(dòng)tab
常用屬性:
app:tabIndicatorColor :指示線(xiàn)的顏色
app:tabIndicatorHeight :指示線(xiàn)的高度
app:tabSelectedTextColor : tab選中時(shí)的字體顏色
app:tabMode="scrollable" : 默認(rèn)是fixed叶撒,固定的;scrollable:可滾動(dòng)的
各種使用場(chǎng)景:
1.默認(rèn)使用樣式耐版,結(jié)合Viewpager使用:
效果圖:
activity_main.xml布局:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.tablayoutusecase.defaultuse.MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="45dp"
android:background="@color/colorPrimaryDark">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="一般用法"
android:textColor="#fff"
android:textSize="16sp"/>
</RelativeLayout>
<android.support.design.widget.TabLayout
android:id="@+id/tablayout"
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"/>
</LinearLayout>
MainActivity使用:根據(jù)title長(zhǎng)度祠够,設(shè)置文字title,設(shè)置fragment粪牲,設(shè)置viewpager聯(lián)動(dòng)古瓤,使用的是Tablayout默認(rèn)屬性。
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.example.tablayoutusecase.R;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
private TabLayout tabLayout;
private ViewPager viewPager;
private FmPagerAdapter pagerAdapter;
private ArrayList<Fragment> fragments = new ArrayList<>();
private String[] titles = new String[]{"最新","熱門(mén)","我的"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init() {
tabLayout = (TabLayout) findViewById(R.id.tablayout);
viewPager = (ViewPager) findViewById(R.id.viewpager);
for(int i=0;i<titles.length;i++){
fragments.add(new TabFragment());
tabLayout.addTab(tabLayout.newTab());
}
tabLayout.setupWithViewPager(viewPager,false);
pagerAdapter = new FmPagerAdapter(fragments,getSupportFragmentManager());
viewPager.setAdapter(pagerAdapter);
for(int i=0;i<titles.length;i++){
tabLayout.getTabAt(i).setText(titles[i]);
}
}
}
2.設(shè)置Tablayout屬性:
效果圖:
用Tablayout屬性寫(xiě)一個(gè)style虑瀑,給需要的Tablayout引用湿滓。
<style name="MyTablayoutstyle" parent="Base.Widget.Design.TabLayout">
<item name="tabBackground">@color/white</item>
<item name="tabIndicatorColor">@color/green</item>
<item name="tabIndicatorHeight">2dp</item>
<item name="tabSelectedTextColor">@color/green</item>
<item name="android:textSize">15sp</item>
<item name="android:textColor">@color/text</item>
</style>
Tablayout引用:
<android.support.design.widget.TabLayout
android:id="@+id/tab1"
style="@style/MyTablayoutstyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
3.Tablayout去掉指示線(xiàn):
這種很easy滴须,給tabIndicatorHeight屬性設(shè)置0dp舌狗,或者給tabSelectedTextColor屬性設(shè)置透明,就不顯示指示線(xiàn)了扔水。
4.修改指示線(xiàn)長(zhǎng)度:
怎么辦呢痛侍,在布局里怎么打也打不出來(lái)這個(gè)所謂的”tabIndicatorWidth“屬性,那就點(diǎn)進(jìn)去Tablayout類(lèi)里面找魔市,看它是怎么實(shí)現(xiàn)指示線(xiàn)的主届。
找到有如下屬性,即有SlidingTabStrip內(nèi)部類(lèi):
private final SlidingTabStrip mTabStrip;
通過(guò)閱讀發(fā)現(xiàn)該類(lèi)就是設(shè)置指示線(xiàn)的待德,繼承于Linearylayout君丁。那么我們可以通過(guò)反射獲取Tablayout的mTabStrip,循環(huán)獲取到子view将宪,設(shè)置leftMargin绘闷,rightMargin就可以壓縮tab的寬度了橡庞。
一不做二不休,IndicatorLineUtil實(shí)現(xiàn)類(lèi):
import android.content.res.Resources;
import android.support.design.widget.TabLayout;
import android.util.TypedValue;
import android.view.View;
import android.widget.LinearLayout;
import java.lang.reflect.Field;
public class IndicatorLineUtil {
/**
* 調(diào)節(jié)tablayout指示線(xiàn)寬度
* @param tabs
* @param leftDip
* @param rightDip
*/
public static void setIndicator(TabLayout tabs, int leftDip, int rightDip) {
Class<?> tabLayout = tabs.getClass();
Field tabStrip = null;
try {
tabStrip = tabLayout.getDeclaredField("mTabStrip");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
tabStrip.setAccessible(true);
LinearLayout llTab = null;
try {
llTab = (LinearLayout) tabStrip.get(tabs);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
int left = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, leftDip, Resources.getSystem().getDisplayMetrics());
int right = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, rightDip, Resources.getSystem().getDisplayMetrics());
for (int i = 0; i < llTab.getChildCount(); i++) {
View child = llTab.getChildAt(i);
child.setPadding(0, 0, 0, 0);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 1);
params.leftMargin = left;
params.rightMargin = right;
child.setLayoutParams(params);
child.invalidate();
}
}
}
tablayout調(diào)用此方法:注意:margin數(shù)值不能設(shè)置過(guò)大印蔗,不然tab寬度壓縮為0整個(gè)tablayout就不顯示了扒最。
tab3.post(new Runnable() {
@Override
public void run() {
IndicatorLineUtil.setIndicator(tab3, 40, 40);
}
});
5.設(shè)置默認(rèn)圖標(biāo):
still easy,Tablayout自帶了setIcon()方法設(shè)置圖標(biāo)資源华嘹,不過(guò)這中效果很別扭吧趣,臉被拉長(zhǎng)了。不服耙厚,就自己造一個(gè)啊强挫,造就造!
tabLayout.getTabAt(i).setText(titles[i]).setIcon(pics[i]);
6.自己造tab樣式:
創(chuàng)建圖標(biāo)和文字布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:gravity="center">
<ImageView
android:id="@+id/imageview"
android:layout_gravity="center"
android:layout_width="24dp"
android:layout_height="24dp" />
<TextView
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:textSize="14sp"
android:layout_marginLeft="8dp"/>
</LinearLayout>
這里是圖標(biāo)居左薛躬,那我要改為圖標(biāo)上下左右呢纠拔?都自定義view了,你上天都行泛豪。
/**
* 設(shè)置自定義位置圖標(biāo)
*/
private void setCustomIcon() {
tabLayout2 = (TabLayout) findViewById(R.id.tablayout2);
for(int i=0;i<titles.length;i++){
tabLayout2.addTab(tabLayout2.newTab());
}
for(int i=0;i<titles.length;i++){
tabLayout2.getTabAt(i).setCustomView(makeTabView(i));
}
}
/**
* 引入布局設(shè)置圖標(biāo)和標(biāo)題
* @param position
* @return
*/
private View makeTabView(int position){
View tabView = LayoutInflater.from(this).inflate(R.layout.tab_text_icon,null);
TextView textView = tabView.findViewById(R.id.textview);
ImageView imageView = tabView.findViewById(R.id.imageview);
textView.setText(titles[position]);
imageView.setImageResource(pics[position]);
return tabView;
}
7.tab數(shù)量太多稠诲,超出屏幕,就像今日頭條的分類(lèi)一樣诡曙,那就擠在一起了啊臀叙。不怕,我們有app:tabMode="scrollable" 屬性价卤,讓Tablayout變得可滾動(dòng)劝萤,可超出屏幕。
布局引入:
<android.support.design.widget.TabLayout
android:id="@+id/tablayout3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabSelectedTextColor="@color/green"
android:layout_marginTop="20dp"
app:tabMode="scrollable"
android:background="@color/white"/>
最后大合唱完整Activity:
import android.support.design.widget.TabLayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.tablayoutusecase.R;
public class SetStyleActivity extends AppCompatActivity {
private TabLayout tab1,tab2,tab3;
private TabLayout tabLayout,tabLayout2,tabLayout3;
private String[] titles = new String[]{"最新","熱門(mén)","我的"};
private String[] longTitles = new String[]{"推薦","熱點(diǎn)","北京","視頻","社會(huì)","圖片","娛樂(lè)","科技","汽車(chē)"};
private int[] pics = new int[]{R.mipmap.subtitle_left_roll_h,R.mipmap.subtitle_middle_roll_h,R.mipmap.subtitle_right_roll_h};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_usecase);
setTab1();
setTab2();
setTab3();
setDefaultIcon();
setCustomIcon();
setScroll();
}
private void setTab1(){
tab1 = (TabLayout) findViewById(R.id.tab1);
for(int i=0;i<titles.length;i++){
tab1.addTab(tab1.newTab());
tab1.getTabAt(i).setText(titles[i]);
}
}
private void setTab2(){
tab2 = (TabLayout) findViewById(R.id.tab2);
for(int i=0;i<titles.length;i++){
tab2.addTab(tab2.newTab());
tab2.getTabAt(i).setText(titles[i]);
}
}
private void setTab3(){
tab3 = (TabLayout) findViewById(R.id.tab3);
for(int i=0;i<titles.length;i++){
tab3.addTab(tab3.newTab());
tab3.getTabAt(i).setText(titles[i]);
}
tab3.post(new Runnable() {
@Override
public void run() {
IndicatorLineUtil.setIndicator(tab3, 40, 40);
}
});
}
/**
* 設(shè)置默認(rèn)圖標(biāo)
*/
private void setDefaultIcon() {
tabLayout = (TabLayout) findViewById(R.id.tablayout);
for(int i=0;i<titles.length;i++){
tabLayout.addTab(tabLayout.newTab());
}
for(int i=0;i<titles.length;i++){
tabLayout.getTabAt(i).setText(titles[i]).setIcon(pics[i]);
}
}
/**
* 設(shè)置自定義位置圖標(biāo)
*/
private void setCustomIcon() {
tabLayout2 = (TabLayout) findViewById(R.id.tablayout2);
for(int i=0;i<titles.length;i++){
tabLayout2.addTab(tabLayout2.newTab());
}
for(int i=0;i<titles.length;i++){
tabLayout2.getTabAt(i).setCustomView(makeTabView(i));
}
}
private void setScroll(){
tabLayout3 = (TabLayout) findViewById(R.id.tablayout3);
for(int i=0;i<longTitles.length;i++){
tabLayout3.addTab(tabLayout3.newTab());
}
for(int i=0;i<longTitles.length;i++){
tabLayout3.getTabAt(i).setText(longTitles[i]);
}
}
/**
* 引入布局設(shè)置圖標(biāo)和標(biāo)題
* @param position
* @return
*/
private View makeTabView(int position){
View tabView = LayoutInflater.from(this).inflate(R.layout.tab_text_icon,null);
TextView textView = tabView.findViewById(R.id.textview);
ImageView imageView = tabView.findViewById(R.id.imageview);
textView.setText(titles[position]);
imageView.setImageResource(pics[position]);
return tabView;
}
}
另外慎璧,我用過(guò)這個(gè)XTablayout
效果也還不錯(cuò)床嫌,可以自定義分割線(xiàn),指示線(xiàn)長(zhǎng)度胸私,字體加粗等功能厌处。
我明明是個(gè)程序員,卻怎么要老是做圖岁疼,藍(lán)瘦香菇阔涉。
好了,Tablayout各種使用場(chǎng)景就講解完了捷绒,代碼在頂端瑰排。覺(jué)得有用的話(huà)關(guān)注我一起學(xué)習(xí)吧。