TabLayout與ViewPager的聯合使用

TabLayout

TabLayout是Google官方的design-support jar包中的一個組件。java

可是TabLayout有一個致命的缺點,那就是沒辦法進行滑動切換,只能經過點擊切換。爲了彌補這個缺點,google提供了一個方法能夠將TabLayout與ViewPager結合在一塊兒,實現滑動切換的效果。android

TabLayout的一些屬性

  • tabMaxWidth: tab tiem的最大寬度,當app:tabMode="fixed"時不起做用git

  • tabIndicatorColor: TabLayout指示器的顏色github

  • tabIndicatorHeight: TabLayout指示器的高度app

  • tabPaddingStart: 距離開始的長度ide

  • tabPaddingEnd: 距離結束的長度函數

  • tabBackground: 背景字體

  • tabTextAppearance: TableLayout title字體屬性ui

  • tabSelectedTextColor: 當前選擇的字體的tab的字體顏色this

如何使用


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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".activities.MainActivity">

    <android.support.design.widget.TabLayout
        android:id="@+id/tablayout"
        android:layout_width="match_parent"
        android:layout_height="?android:actionBarSize"
        android:background="@color/primary"
        app:tabMode="fixed"
        app:tabSelectedTextColor="@color/accent" />

    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/tablayout" />

</RelativeLayout>

適配器

public class VPAndTLAdapter extends FragmentStatePagerAdapter {

    private List<String> tabNames;
    private List<BaseFragment> fragments;

    public VPAndTLAdapter(FragmentManager fm, List<String> tabNames, List<BaseFragment> fragments) {
        super(fm);
        this.tabNames = tabNames;
        this.fragments = fragments;
    }
    @Override
    public Fragment getItem(int position) {
        return fragments.get(position);
    }
    @Override
    public int getCount() {
        return fragments.size();
    }
    /**
    *這個函數就是給TabLayout的Tab設定Title
    */
    @Override
    public CharSequence getPageTitle(int position) {
        return tabNames.get(position);
    }
}

Fragment

TabLayout的每個Tab就對應着與一個Fragment

public class GraphFragment extends Fragment {

    private static final String TAG = "GraphFragment";
    private View rootView;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        rootView = inflater.inflate(R.layout.fragment_graph, container, false);
        return rootView;
    }
    @Override
    public void onStart() {
        super.onStart();
    }
}

MainActivity

private static final String TAB_NAME_1 = "流量圖像";
private static final String TAB_NAME_2 = "監控視頻";
private static final String TAB_NAME_3 = "我的中心";
private List<String> tabNames;
private List<BaseFragment> fragments;

private void initTablayoutAndViewPager() {
        tabNames = new ArrayList<>();
        fragments = new ArrayList<>();
        tabNames.add(TAB_NAME_1);
        tabNames.add(TAB_NAME_2);
        tabNames.add(TAB_NAME_3);

        mVideoFragment = new VideoFragment();
        mPersonFragment = new PersonFragment();
        mGraphFragment = new GraphFragment();
        fragments.add(mGraphFragment);
        fragments.add(mVideoFragment);
        fragments.add(mPersonFragment);

        VPAndTLAdapter mVpAndTLAdapter = new VPAndTLAdapter(getSupportFragmentManager(), tabNames, fragments);
        mViewPager.setAdapter(mVpAndTLAdapter);
        mTabLayout.setupWithViewPager(mViewPager);
    }

這樣就能夠實現滑動切換tab的效果啦。

缺陷&嘗試

雖然基本上實現了滑動Tab的效果,可是有一個缺點,那就是沒法爲Tab設置圖標。

以前我嘗試過這樣添加圖標,可是失敗了:

for (String tabName : tabNames) {
    mTabLayout.addTab(mTabLayout.newTab().setIcon(getResources().getDrawable(R.mipmap.ic_launcher)));
}

這種方法失敗的緣由是:以前設置的tab被適配器類中getPageTitle()覆蓋了,因此沒法顯示圖片。

SpannableString介紹

想要在Tab上顯示圖片就要用到這個類。
首先,SpannableString這個類實現了CharSequence這個接口,因此能夠在Adapter中的getPageTitle()中返回。

那麼,SpannableString這個類的做用到底有哪些呢?最簡單的來講,它能夠實如今字符串中插入一些別的東西,例如表情,顏色,甚至是HTML中的某些標籤。例如:QQ的對話View(應該是這樣實現的)

構造方法

SpannableString的構造方法須要一個參數:CharSequence(沒錯就是這個超級字符串的基本顯示內容)

public SpannableString(CharSequence source) {
    super(source, 0, source.length());
}

setSpan()方法

setSpan()就是這個類的核心內容了:

public void setSpan(Object what, int start, int end, int flags) {
    super.setSpan(what, start, end, flags);
}

參數:

  • 第一個參數爲要向這個超級字符串中添加的內容。例如:前景色、背景色、圖片、連接、下劃線等等,稍後爲你們展現

  • 第二個參數爲開始的位置(0爲開始)

  • 第三個參數爲結束的位置

  • 最後一個參數用來標識在span範圍內的文本先後輸入新的字符時是否也應用這個效果,分別有:

    • Spanned.SPAN_EXCLUSIVE_EXCLUSIVE(先後都不包括)

    • Spanned.SPAN_INCLUSIVE_EXCLUSIVE(前面包括,後面不包括)

    • Spanned.SPAN_EXCLUSIVE_INCLUSIVE(前面不包括,後面包括)

    • Spanned.SPAN_INCLUSIVE_INCLUSIVE(先後都包括)

例子

添加前景色

spannableString.setSpan(new ForegroundColorSpan(Color.BLUE), 1, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

添加背景色

spannableString.setSpan(new BackgroundColorSpan(Color.RED), 1, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

添加下劃線

spannableString.setSpan(new UnderlineSpan(), 0, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

添加圖片

spannableString.setSpan(new ImageSpan(mContext, R.id.ic_launcher, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

開始改造

首先要修改Adapter的構造方法

Adapter

private List<String> tabNames;
private List<BaseFragment> fragments;
private List<Integer> tabIcs;
private SpannableString spannableString;
private Context mContext;

public VPAndTLAdapter(FragmentManager fm, Context mContext, List<String> tabNames, List<BaseFragment> fragments, List<Integer> tabIcs) {
    super(fm);
    this.mContext = mContext; //獲取圖片資源的時候須要Context參數
    this.fragments = fragments;
    this.tabNames = tabNames; //每一個Tab上的文字、能夠爲null
    this.tabIcs = tabIcs; //每一個Tab上的圖標,能夠爲null
}

接着就是修改getPageTitle()這個方法:

@Override
public CharSequence getPageTitle(int position) {
    if (tabNames == null) {     //不設置文字
        spannableString = new SpannableString(" ");  //這裏要給圖片留一個字符的空間。
    } else {
        spannableString = new SpannableString(" " + tabNames.get(position));
    }
    if (tabIcs != null) {    //設置圖標
        spannableString.setSpan(new ImageSpan(mContext, tabIcs.get(position)), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    }
    return spannableString;
}

設置TabLayout的屬性

不得不說,這個問題耗了我好長時間:(

首先在styles.xml文件內定義這樣一個樣式:

<style name="MyCustomTextAppearance" parent="TextAppearance.Design.Tab">
      <item name="textAllCaps">false</item>
      <item name="android:textAllCaps">false</item>
      <!-- 注意這兩個屬性必定要寫,缺一不可,不然顯示不出圖片! -->
</style>

接着設置TabLayout的屬性:

app:tabTextAppearance="@style/MyCustomTextAppearance"

本文來自http://qiaoyunrui.github.io/2016/04/09/TABLayoutAndViewPager/

相關文章
相關標籤/搜索