Tablayout使用全解敬扛,一篇就夠了

前言

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è)。

github代碼直通車(chē)

先上效果圖:分別為設(shè)置tab屬性拼岳、去掉指示線(xiàn)枝誊、設(shè)置指示線(xiàn)長(zhǎng)度、設(shè)置圖標(biāo)tab惜纸、超出屏幕滾動(dòng)tab


使用場(chǎng)景
常用屬性:
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使用:

效果圖:


giphy.gif

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屬性:

效果圖:


image.png

用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):
image.png

這種很easy滴须,給tabIndicatorHeight屬性設(shè)置0dp舌狗,或者給tabSelectedTextColor屬性設(shè)置透明,就不顯示指示線(xiàn)了扔水。

4.修改指示線(xiàn)長(zhǎng)度:
image.png

怎么辦呢痛侍,在布局里怎么打也打不出來(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;
image.png

通過(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):
image.png

still easy,Tablayout自帶了setIcon()方法設(shè)置圖標(biāo)資源华嘹,不過(guò)這中效果很別扭吧趣,臉被拉長(zhǎng)了。不服耙厚,就自己造一個(gè)啊强挫,造就造!
tabLayout.getTabAt(i).setText(titles[i]).setIcon(pics[i]);

6.自己造tab樣式:
image.png

創(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)劝萤,可超出屏幕。
image.png

布局引入:

    <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í)吧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末暖侨,一起剝皮案震驚了整個(gè)濱河市椭住,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌字逗,老刑警劉巖京郑,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件显押,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡傻挂,警方通過(guò)查閱死者的電腦和手機(jī)乘碑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)金拒,“玉大人兽肤,你說(shuō)我怎么就攤上這事⌒髋祝” “怎么了资铡?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)幢码。 經(jīng)常有香客問(wèn)我笤休,道長(zhǎng),這世上最難降的妖魔是什么症副? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任店雅,我火速辦了婚禮,結(jié)果婚禮上贞铣,老公的妹妹穿的比我還像新娘闹啦。我一直安慰自己,他們只是感情好辕坝,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布窍奋。 她就那樣靜靜地躺著,像睡著了一般酱畅。 火紅的嫁衣襯著肌膚如雪琳袄。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,146評(píng)論 1 297
  • 那天纺酸,我揣著相機(jī)與錄音窖逗,去河邊找鬼。 笑死吁峻,一個(gè)胖子當(dāng)著我的面吹牛滑负,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播用含,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼帮匾!你這毒婦竟也來(lái)了啄骇?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤瘟斜,失蹤者是張志新(化名)和其女友劉穎缸夹,沒(méi)想到半個(gè)月后痪寻,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡虽惭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年橡类,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片芽唇。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡顾画,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出匆笤,到底是詐尸還是另有隱情研侣,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布炮捧,位于F島的核電站庶诡,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏咆课。R本人自食惡果不足惜末誓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望书蚪。 院中可真熱鬧基显,春花似錦、人聲如沸善炫。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)箩艺。三九已至窜醉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間艺谆,已是汗流浹背榨惰。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留静汤,地道東北人琅催。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像虫给,于是被迫代替她去往敵國(guó)和親藤抡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353