TabLayout:另一種Tab的實現方式

尊重原創轉載請註明:From AigeStudio(http://blog.csdn.net/aigestudio)Power by Aige 侵權必究!

炮兵 鎮樓

在5.0以前我們想要實現像網易新聞客戶端那樣的的Tab可以有很多種選擇:

比如古老的TabHost,3.0後ActionBar所提供的Tab,以及各種成熟的Tab開源控件等,都可以直接或間接地實現Tab的效果。然而,對於這樣一種使用極多的控件,Android是不會放棄將它納入麾下的打算的,於是乎在5.0後放出的design包中Android就厚顏無恥地推出了自家官方的TabLayout控件來方便地實現類似的效果。其實這玩意跟ActionBar的Tab沒什麼卵的區別,只是說它更符合谷歌自家的MD設計理念,不過在實際使用中這玩意略顯蛋疼,廢話不多說,我們還是直接切入主題,要想使用TabLayout你就得導入Android的design包:

<code class="hljs matlab has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">dependencies <span class="hljs-cell" style="box-sizing: border-box;">{
    compile <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'com.android.support:design:22.2.0'</span>
}</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

然後在你的佈局里加入TabLayout就行了:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

</RelativeLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

這裏需要注意的是design包中有些資源依賴於5.0,這是不是說我們就不能使用了呢,不是的,我們可以從AppCompat獲得這些資源,將當前Activity的主題設置爲Theme.AppCompat或其子類即可:

<activity
    android:name="tablayout.TabLayoutActivity"
    android:theme="@style/Theme.AppCompat" />
  • 1
  • 2
  • 3

當然現在你運行不會看到任何東西,因爲我們沒往裏面家東西嘛,與ActionBar類似的是TabLayout添加Tab也很方便,只需要調用其addTab方法即可:

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">TabLayoutActivity</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Activity</span> {</span>
    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onCreate</span>(Bundle savedInstanceState) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.onCreate(savedInstanceState);
        setContentView(R.layout.ac_tab_layout);

        TabLayout tabLayout = (TabLayout) findViewById(R.id.ac_tab_layout);

        TabLayout.Tab tab1 = tabLayout.newTab().setText(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Tab1"</span>);
        tabLayout.addTab(tab1);
        TabLayout.Tab tab2 = tabLayout.newTab().setText(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Tab2"</span>);
        tabLayout.addTab(tab2);
        TabLayout.Tab tab3 = tabLayout.newTab().setText(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Tab3"</span>);
        tabLayout.addTab(tab3);
    }
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul>

運行效果如下:

非常簡單,不過需要注意的是,這裏的Tab類是TabLayout的一個靜態內部類,並且其構造方法是包內可訪問的,也就是說你無法在外部構造其實例,只能通過TabLayout的newTab方法:

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">TabLayout</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">HorizontalScrollView</span> {</span>
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// ......省去很多代碼......</span>

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Tab</span> {</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// ......省去很多代碼......</span>

        Tab(TabLayout parent) {
            mPosition = -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;
            mParent = parent;
        }
    }

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Tab <span class="hljs-title" style="box-sizing: border-box;">newTab</span>() {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Tab(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);
    }

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// ......省去很多代碼......</span>
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li></ul>

addTab方法有四個不同的實現,拿參數最多的addTab(Tab tab, int position, boolean setSelected)方法來說,第一個參數tab就不說了,第二個參數position表示當前Tab需要插入的位置,其值必須小於當前TabLayout所擁有的Tab總數減一,如果大於則會報出數組下標溢出異常,這點很好理解,最後的boolean參數setSelected與其名意義一樣,表示當前添加的Tab是否爲選中狀態,拿上面代碼中的第三個tab3來說,我們修改其代碼如下:

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">TabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Tab</span> tab3 = tabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.newTab</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setText</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Tab3"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
tabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addTab</span>(tab3, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, true)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

運行後tab3默認就會是被選中狀態:

TabLayout中的公共方法不算多,大多都很好理解,不過有一個方法愛哥表示對其極度不爽,setScrollPosition從名字上來看它是用來設置滾動位置的,大家注意我們的TabLayout中被選中的Tab下方不是有根線麼,我們可以通過這個方法來設置它的位置。首先我們在佈局中添加一個按鈕:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

    <Button
        android:id="@+id/ac_tab_btn"
        android:layout_width="wrap_content"
        android:layout_centerInParent="true"
        android:layout_height="wrap_content"
        android:text="Move" />
</RelativeLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

然後呢爲這個按鈕綁定一個點擊事件監聽並在其中調用setScrollPosition方法:

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">Button btnAdd = (Button) findViewById(R.id.ac_tab_btn);
btnAdd.setOnClickListener(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> View.OnClickListener() {
    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onClick</span>(View v) {
        tabLayout.setScrollPosition(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.5</span>F, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>);
    }
});</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

setScrollPosition方法的三個參數根據官方文檔給出的解釋如下:

第一個參數表示當前Tab的位置,第二個參數是偏移值,從文檔中看到該值的取值範圍是0到1的一個半開區間,最後一個參數很好理解表示是否置移動後位置所對應的Tab爲選中狀態,打個比方,如果我從0移動到1的位置,如果updateSelectedText爲true,那麼1這個位置上的文本就會是一個選中狀態。上面的代碼中我們只是簡單地讓下方的橫條從0的Tab位置移動到一個0.5F的位置,效果如下:

可能大家會覺得納悶,這個0.5F是個吊毛意思,其實positionOffset這個參數是一個倍數值,它的計算邏輯有些複雜,從源碼中看setScrollPosition的邏輯,大致分爲兩步:

public void setScrollPosition(int position, float positionOffset, boolean updateSelectedText) {
    if (isAnimationRunning(getAnimation()))
        return;
    if (position < 0 || position >= mTabStrip.getChildCount())
        return;
    mTabStrip.setIndicatorPositionFromTabPosition(position, positionOffset);
    scrollTo(calculateScrollXForTab(position, positionOffset), 0);
    if (updateSelectedText)
        setSelectedTabView(Math.round((float) position + positionOffset));
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

首先是

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">mTabStrip<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setIndicatorPositionFromTabPosition</span>(position, positionOffset)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

這段的調用,其目的很簡單,就是設置Tab下方的那個橫條的位置,先是調用SlidingTabStrip的setIndicatorPositionFromTabPosition方法賦值:

<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> setIndicatorPositionFromTabPosition(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> position, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> positionOffset) {
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (TabLayout.isAnimationRunning(getAnimation())) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
    } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {
        mSelectedPosition = position;
        mSelectionOffset = positionOffset;
        updateIndicatorPosition();
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
    }
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>

然後又調用了updateIndicatorPosition來做具體的位置更新操作:

private void updateIndicatorPosition() {
    View selectedTitle = getChildAt(mSelectedPosition);
    int left;
    int right;
    if (selectedTitle != null && selectedTitle.getWidth() > 0) {
        left = selectedTitle.getLeft();
        right = selectedTitle.getRight();
        if (mSelectionOffset > 0.0F && mSelectedPosition < getChildCount() - 1) {
            View nextTitle = getChildAt(mSelectedPosition + 1);
            left = (int) (mSelectionOffset * (float) nextTitle.getLeft() + (1.0F - mSelectionOffset) * (float) left);
            right = (int) (mSelectionOffset * (float) nextTitle.getRight() + (1.0F - mSelectionOffset) * (float) right);
        }
    } else {
        left = right = -1;
    }
    setIndicatorPosition(left, right);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

首先是得到當前Tab左右的座標值,然後嘗試獲取下一個Tab,如果有,那麼根據相對位置計算最終的左右座標,沒有則不改變使用當前的左右座標,這很好理解,最後通過setIndicatorPosition放啊分設置最終的橫條位置:

<code class="hljs vbscript has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> void setIndicatorPosition(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">int</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">left</span>, <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">int</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">right</span>) {
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">left</span> != mIndicatorLeft || <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">right</span> != mIndicatorRight) {
        mIndicatorLeft = <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">left</span>;
        mIndicatorRight = <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">right</span>;
        ViewCompat.postInvalidateOnAnimation(this);
    }
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

回到setScrollPosition方法中再看看第二步滾動TabLayout到指定位置:

<code class="hljs scss has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-function" style="box-sizing: border-box;">scrollTo(<span class="hljs-function" style="box-sizing: border-box;">calculateScrollXForTab(position, positionOffset)</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>)</span>;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

這一步在默認模式下不會被執行,TabLayout提供兩種模式,一種是填充模式,也就是默認模式,表示TabLayout不可滾動,其寬度有一個最大值,所有的Tab則會擠在這個寬度中:

該模式的常量值爲MODE_FIXED = 1,而我們可以通過TabLayout的setTabMode方法來設置其模式,這裏我們將TabLayout的模式改爲可滾動:

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">tabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setTabMode</span>(TabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.MODE</span>_SCROLLABLE)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

TabLayout.MODE_SCROLLABLE的常量值爲0,這時候再看看效果:

這時候TabLayout變爲可滾動而所有的Tab均顯示完整。好我們現在回過頭來看看

<code class="hljs scss has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-function" style="box-sizing: border-box;">scrollTo(<span class="hljs-function" style="box-sizing: border-box;">calculateScrollXForTab(position, positionOffset)</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>)</span>;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

這段代碼,scrollTo這個方法相信大家做過滑動都不會太陌生,其會將當前視圖滾動至指定的座標位置,TabLayout是一個水平滾動視圖,因此其Y座標滾動至恆爲0,而X座標則通過calculateScrollXForTab這個方法來計算:

private int calculateScrollXForTab(int position, float positionOffset) {
    if (mMode == 0) {
        View selectedChild = mTabStrip.getChildAt(position);
        View nextChild = position + 1 >= mTabStrip.getChildCount() ? null : mTabStrip.getChildAt(position + 1);
        int selectedWidth = selectedChild == null ? 0 : selectedChild.getWidth();
        int nextWidth = nextChild == null ? 0 : nextChild.getWidth();
        return (int) (((float) selectedChild.getLeft() + (float) (selectedWidth + nextWidth) * positionOffset * 0.5F + (float) selectedChild.getWidth() * 0.5F) - (float) getWidth() * 0.5F);
    } else {
        return 0;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

這裏可以看到先做了一個判斷,如果模式爲填充也就是MODE_FIXED的情況下是不需要滾動的,只有當模式爲MODE_SCROLLABLE時纔會去滾動,X座標的計算邏輯與updateIndicatorPosition方法中的計算邏輯類似,都是通過當前Tab與下一個Tab的相對關係來計算的。那麼爲什麼愛哥會對setScrollPosition這個方法表示極度不爽呢?首先,這個方法調用的前提根據官方文檔和源碼來看是需要相鄰的兩個Tab共同計算的,打個比方,如果我想從第0個Tab跳轉至第1個Tab那麼我就可以這麼幹:

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">TabLayoutActivity</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Activity</span> {</span>
    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onCreate</span>(Bundle savedInstanceState) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.onCreate(savedInstanceState);
        setContentView(R.layout.ac_tab_layout);

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> TabLayout tabLayout = (TabLayout) findViewById(R.id.ac_tab_layout);

        TabLayout.Tab tab1 = tabLayout.newTab().setText(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Tab1"</span>);
        tabLayout.addTab(tab1);
        TabLayout.Tab tab2 = tabLayout.newTab().setText(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Tab2"</span>);
        tabLayout.addTab(tab2);
        TabLayout.Tab tab3 = tabLayout.newTab().setText(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Tab3"</span>);
        tabLayout.addTab(tab3);

        tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);

        Button btnAdd = (Button) findViewById(R.id.ac_tab_btn);
        btnAdd.setOnClickListener(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> View.OnClickListener() {
            <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onClick</span>(View v) {
                tabLayout.setScrollPosition(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>F, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>);
        });
    }
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li></ul>

從第0個Tab開始,偏移值爲一個單位,效果如下:

注意到這裏的一個BUG沒有,淡定,好戲在後頭,大家想想雖說官方文檔建議第二個參數的取值區間在0到1,但是我們完全可以考慮將該值設置大於1對吧,假設,僅僅是個假設,我們將其設爲2,那麼是否可以表示我們能直接從第0個Tab直接跳轉到第2個Tab呢?答案好像是肯定的:

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">btnAdd.setOnClickListener(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> View.OnClickListener() {
    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onClick</span>(View v) {
        tabLayout.setScrollPosition(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>F, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>);
});</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>

運行效果如下:

是不是有點意外?但是注意,這種想法是錯誤的!!!這裏之所以能夠直接跳轉到第2個Tab是因爲在這個例子中我們的每個Tab寬度都是一樣的,如果我們將Tab稍作修改:

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">TabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Tab</span> tab1 = tabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.newTab</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setText</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Aige"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
tabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addTab</span>(tab1)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
TabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Tab</span> tab2 = tabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.newTab</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setText</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"AigeStudio"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
tabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addTab</span>(tab2)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
TabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Tab</span> tab3 = tabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.newTab</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setText</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Studio"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
tabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addTab</span>(tab3)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

這時候你就會看到錯誤的計算顯示了:

當然如果僅僅是相鄰的滾動,這樣做是沒問題的,比如我們從第1個Tab滾動至第2個Tab:

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">TabLayoutActivity</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Activity</span> {</span>
    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onCreate</span>(Bundle savedInstanceState) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.onCreate(savedInstanceState);
        setContentView(R.layout.ac_tab_layout);

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> TabLayout tabLayout = (TabLayout) findViewById(R.id.ac_tab_layout);

        TabLayout.Tab tab1 = tabLayout.newTab().setText(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Aige"</span>);
        tabLayout.addTab(tab1);
        TabLayout.Tab tab2 = tabLayout.newTab().setText(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"AigeStudio"</span>);
        tabLayout.addTab(tab2, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>);
        TabLayout.Tab tab3 = tabLayout.newTab().setText(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Studio"</span>);
        tabLayout.addTab(tab3);

        tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);

        Button btnAdd = (Button) findViewById(R.id.ac_tab_btn);
        btnAdd.setOnClickListener(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> View.OnClickListener() {
            <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onClick</span>(View v) {
                tabLayout.setScrollPosition(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>F, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>);
            }
        });
    }
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li></ul>

這樣就沒問題:

使用setScrollPosition的另一個問題是,滾動時Tab底部那個橫條切換生硬,不知道大家注意到沒,沒注意到往上看之前的一些切換動圖,非常生硬,然而如果我們用另外一種方式來做這種切換就顯得很帶感了,Tab類中提供了一個select方法來設置當前Tab被選中:

<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> final <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> Tab {
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// ......省去很多代碼......</span>

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">select</span>() {
        mParent.selectTab(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);
    }

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// ......省去很多代碼......</span>
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

這個方法所帶來的效果就很不一樣了,比如我們點擊設置第三個Tab被選中:

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">TabLayoutActivity</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Activity</span> {</span>
    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onCreate</span>(Bundle savedInstanceState) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.onCreate(savedInstanceState);
        setContentView(R.layout.ac_tab_layout);

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> TabLayout tabLayout = (TabLayout) findViewById(R.id.ac_tab_layout);

        TabLayout.Tab tab1 = tabLayout.newTab().setText(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Aige"</span>);
        tabLayout.addTab(tab1);
        TabLayout.Tab tab2 = tabLayout.newTab().setText(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"AigeStudio"</span>);
        tabLayout.addTab(tab2);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> TabLayout.Tab tab3 = tabLayout.newTab().setText(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Studio"</span>);
        tabLayout.addTab(tab3);

        tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);

        Button btnAdd = (Button) findViewById(R.id.ac_tab_btn);
        btnAdd.setOnClickListener(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> View.OnClickListener() {
            <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onClick</span>(View v) {
                tab3.select();
            }
        });
    }
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li></ul>

效果是不是要動感的多呢:

從源碼裏可以看到select方法本質是調用了TabLayout中的selectTab方法:

<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> selectTab(Tab tab) {
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mSelectedTab == tab) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mSelectedTab != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mOnTabSelectedListener != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>)
                mOnTabSelectedListener.onTabReselected(mSelectedTab);
            animateToTab(tab.getPosition());
        }
    } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> newPosition = tab == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> ? -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span> : tab.getPosition();
        setSelectedTabView(newPosition);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> ((mSelectedTab == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> || mSelectedTab.getPosition() == -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>) && newPosition != -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>)
            setScrollPosition(newPosition, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.0</span>F, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>
            animateToTab(newPosition);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mSelectedTab != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> && mOnTabSelectedListener != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>)
            mOnTabSelectedListener.onTabUnselected(mSelectedTab);
        mSelectedTab = tab;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mSelectedTab != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> && mOnTabSelectedListener != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>)
            mOnTabSelectedListener.onTabSelected(mSelectedTab);
    }
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li></ul>

在該方法中比較重要的就是一個animateToTab方法的調用,該方法是產生動畫效果的關鍵:

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">animateToTab</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> newPosition) {
    clearAnimation();
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (newPosition == -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>)
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (getWindowToken() == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> || !ViewCompat.isLaidOut(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>)) {
        setScrollPosition(newPosition, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.0</span>F, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
    }
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> startScrollX = getScrollX();
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> targetScrollX = calculateScrollXForTab(newPosition, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.0</span>F);
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> duration = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (startScrollX != targetScrollX) {
        ValueAnimatorCompat animator = ViewUtils.createAnimator();
        animator.setInterpolator(AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR);
        animator.setDuration(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>);
        animator.setIntValues(startScrollX, targetScrollX);
        animator.setUpdateListener(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ValueAnimatorCompat.AnimatorUpdateListener() {

                                       <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onAnimationUpdate</span>(ValueAnimatorCompat animator) {
                                           scrollTo(animator.getAnimatedIntValue(), <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);
                                       }

                                       <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> TabLayout <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>$<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;


                                       {
                                           <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>$<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> = TabLayout.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>;
                                           <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>();
                                       }
                                   }
        );
        animator.start();
    }
    mTabStrip.animateIndicatorToPosition(newPosition, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>);
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li></ul>

如果你不需要設置Tab的一些監聽的話那麼完全可以通過反射的方式調用該方法滾動Tab至指定位置:

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">public class TabLayoutActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.onCreate</span>(savedInstanceState)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        setContentView(R<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.layout</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.ac</span>_tab_layout)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

        final TabLayout tabLayout = (TabLayout) findViewById(R<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.id</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.ac</span>_tab_layout)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

        TabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Tab</span> tab1 = tabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.newTab</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setText</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Aige"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        tabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addTab</span>(tab1)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        TabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Tab</span> tab2 = tabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.newTab</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setText</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"AigeStudio"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        tabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addTab</span>(tab2)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        TabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Tab</span> tab3 = tabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.newTab</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setText</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Studio"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        tabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addTab</span>(tab3)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        TabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Tab</span> tab4 = tabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.newTab</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setText</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Fuck You"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        tabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addTab</span>(tab4)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        TabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Tab</span> tab5 = tabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.newTab</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setText</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Some of bitch"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        tabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addTab</span>(tab5)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        TabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Tab</span> tab6 = tabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.newTab</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setText</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Android"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        tabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addTab</span>(tab6)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

        tabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setTabMode</span>(TabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.MODE</span>_SCROLLABLE)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

        Button btnAdd = (Button) findViewById(R<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.id</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.ac</span>_tab_btn)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        btnAdd<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setOnClickListener</span>(new View<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.OnClickListener</span>() {
            @Override
            public void onClick(View v) {
                Class <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">clz</span> = tabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getClass</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
                try {
                    Method animateToTab = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">clz</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getDeclaredMethod</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"animateToTab"</span>, new Class[]{int<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.class</span>})<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
                    animateToTab<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setAccessible</span>(true)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
                    animateToTab<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.invoke</span>(tabLayout, new Object[]{<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>})<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
                } catch (Exception e) {
                    e<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.printStackTrace</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
                }
            }
        })<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    }
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li></ul>

運行效果如下:

Tab中還有些其它的方法比如setIcon設置圖標、setTag設置一個Tag標籤還有setCustomView設置一個自定義視圖作爲一個Tab等,這些都比較簡單不多說了:

TabLayout還有個setTabGravity方法可以用來設置TabLayout的佈局方式,該方法只有兩個可選參數GRAVITY_FILL = 0和GRAVITY_CENTER = 1,默認值是GRAVITY_FILL,setTabGravity方法只有在Mode爲MODE_FIXED的情況下才有用,比如現在我們有兩個Tab且這兩個Tab的寬度比TabLayout小,默認情況下Tab的顯示如下:

如果我們將Gravity設置爲GRAVITY_CENTER:

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">tabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setTabMode</span>(TabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.MODE</span>_FIXED)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
tabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setTabGravity</span>(TabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.GRAVITY</span>_CENTER)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

那麼它就會是這個樣子:

不難理解吧。我們還可以通過setOnTabSelectedListener方法爲Tab切換設置監聽器,OnTabSelectedListener接口中有三個方法onTabSelected、onTabUnselected和onTabReselected,前兩個都很好理解不多說,不過要注意的是onTabUnselected總會在onTabSelected前被觸發,而onTabReselected則會在你重複點擊Tab的時候會被觸發。你也可以調用setTabTextColors方法來更改顯示文本的顏色,setTabTextColors接收兩個顏色值分別表示普通狀態的顏色和選中狀態的顏色,當然你也可以提供一個ColorStateList對象:

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">tabLayout<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setTabTextColors</span>(Color<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.RED</span>, Color<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.GREEN</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

效果如下:

這裏要注意的是setTabTextColors方法必須在你添加Tab也就是調用addTab前調用,否則無效,這也是一個bug。還有一點是你無法通過代碼的方式修改指示器也就是Tab下方的那根橫線,因爲那玩意由TabLayout的一個私有內部類SlidingTabStrip控制,其中的方法全TM是non-public的,不過值得欣慰的是你可以在xml中通過屬性來改變它,當然上面我們說到的文本顏色也可以通過這種方式修改:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.TabLayout
        android:id="@+id/ac_tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabIndicatorColor="#FFFFFF"
        app:tabSelectedTextColor="#00FF00"
        app:tabTextColor="#FF0000" />

</RelativeLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

效果如下:

大部分情況下TabLayout都不會單獨使用,一般我們會配合ViewPager來實現一個完整的Tab切換效果,而TabLayout也提供了幾個很簡便的方法來與ViewPager進行關聯交互,先在我們的佈局里加一個ViewPager:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

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

    <android.support.v4.view.ViewPager
        android:id="@+id/ac_tab_vp"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

</LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

然後,然後,然後還是看代碼吧,TabLayout與ViewPager結合的邏輯有點繞:

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">TabLayoutActivity</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Activity</span> {</span>
    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 數據源
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String[] DATA = {<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"AigeStudio"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Aige"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Studio"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Android"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Java"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Design"</span>};

    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onCreate</span>(Bundle savedInstanceState) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.onCreate(savedInstanceState);
        setContentView(R.layout.ac_tab_layout);

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 獲取ViewPager</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> ViewPager viewPager = (ViewPager) findViewById(R.id.ac_tab_vp);

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 構造一個TabPagerAdapter對象</span>
        TabPagerAdapter adapter = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> TabPagerAdapter();

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 獲取ViewPager</span>
        TabLayout tabLayout = (TabLayout) findViewById(R.id.ac_tab_layout);

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 設置TabLayout模式</span>
        tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 設置從PagerAdapter中獲取Tab</span>
        tabLayout.setTabsFromPagerAdapter(adapter);

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 設置Tab的選擇監聽</span>
        tabLayout.setOnTabSelectedListener(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> TabLayout.OnTabSelectedListener() {
            <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onTabSelected</span>(TabLayout.Tab tab) {
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 每當我們選擇了一個Tab就將ViewPager滾動至對應的Page</span>
                viewPager.setCurrentItem(tab.getPosition(), <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>);
            }

            <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onTabUnselected</span>(TabLayout.Tab tab) {
            }

            <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onTabReselected</span>(TabLayout.Tab tab) {
            }
        });
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 構造一個TabLayoutOnPageChangeListener對象</span>
        TabLayout.TabLayoutOnPageChangeListener listener =
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> TabLayout.TabLayoutOnPageChangeListener(tabLayout);

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 設置ViewPager頁面改變後的監聽</span>
        viewPager.addOnPageChangeListener(listener);

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 設置ViewPager的適配器</span>
        viewPager.setAdapter(adapter);
    }

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">TabPagerAdapter</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">PagerAdapter</span> {</span>
        <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> <span class="hljs-title" style="box-sizing: border-box;">getCount</span>() {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> DATA.length;
        }

        <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">isViewFromObject</span>(View view, Object object) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> view == object;
        }

        <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Object <span class="hljs-title" style="box-sizing: border-box;">instantiateItem</span>(ViewGroup container, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> position) {
            TextView tvContent = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> TextView(TabLayoutActivity.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>);
            tvContent.setText(DATA[position]);
            tvContent.setGravity(Gravity.CENTER);
            container.addView(tvContent,
                    ViewPager.LayoutParams.MATCH_PARENT, ViewPager.LayoutParams.WRAP_CONTENT);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> tvContent;
        }

        <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">destroyItem</span>(ViewGroup container, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> position, Object object) {
            container.removeView((View) object);
        }

        <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> CharSequence <span class="hljs-title" style="box-sizing: border-box;">getPageTitle</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> position) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> DATA[position];
        }
    }
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li></ul>

運行效果如下:

其它的不多說,大家注意到我們的代碼中並沒有添加Tab的具體邏輯,但是從運行的結果來看卻實實在在地把我們的Tab標題顯示上去了,這裏主要還是要歸功於TabLayout的setTabsFromPagerAdapter方法,在該方法中TabLayout會通過PagerAdapter的getPageTitle方法獲得Page中的標題並將其封裝成一個Tab添加至TabLayout中:

<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setTabsFromPagerAdapter</span>(PagerAdapter adapter){
    removeAllTabs();
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> count = adapter.getCount(); i < count; i++)
        addTab(newTab().setText(adapter.getPageTitle(i)));
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

這也是爲什麼我們會在PagerAdapter中重寫getPageTitle方法返回數據的原因。同時我們爲TabLayout設置了一個Tab選擇監聽,在Tab被選擇後可以讓滾動至對應的Page,這一步就完成了Tab到Page的事件綁定,那麼當Page改變後又如何影響Tab呢?這時候我們就得爲ViewPager添加一個PageChangeListener,而這個PageChangeListener當然你可以自己去實現,但是TabLayout提供了一個方便的實現類TabLayoutOnPageChangeListener,我們只需構造一個添加到ViewPager即可。是不是覺得邏輯有點亂?一會TabLayout一會ViewPager的,確實,我也覺的,不過TabLayout提供了一個更超級簡便的方法setupWithViewPager來完成與ViewPager的結合,使用方法很簡單,先把ViewPager的相關參數什麼的設置好,比如Adapter什麼的,然後直接調用TabLayout的setupWithViewPager方法設置即可:

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onCreate</span>(Bundle savedInstanceState) {
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.onCreate(savedInstanceState);
    setContentView(R.layout.ac_tab_layout);

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 獲取ViewPager</span>
    ViewPager viewPager = (ViewPager) findViewById(R.id.ac_tab_vp);

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 構造一個TabPagerAdapter對象</span>
    TabPagerAdapter adapter = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> TabPagerAdapter();

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 獲取ViewPager</span>
    TabLayout tabLayout = (TabLayout) findViewById(R.id.ac_tab_layout);

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 設置TabLayout模式</span>
    tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 設置ViewPager的適配器</span>
    viewPager.setAdapter(adapter);

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 設置ViewPager</span>
    tabLayout.setupWithViewPager(viewPager);
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li></ul>

是不是感覺瞬間就簡單了很多…………Fuck。好了TabLayout就囉嗦到這裏,總結就一句話,這貨一定是程序猿心情不好的時候寫的,很多邏輯好奇葩啊有木有~~~~

Demo項目源碼在Github可下載:AndroidViewDemo

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章