1. 程式人生 > >TabLayout+ViewPager+Fragment實現頂部或底部導航欄

TabLayout+ViewPager+Fragment實現頂部或底部導航欄

以前看慕課網的教程,寫過一個微信Tab選項卡切換的例子,使用的是ViewPager+Fragment來實現的,說實話,當時為了實現一些效果,還是寫了蠻多的程式碼,但是,今天介紹的TabLayout+ViewPager+Fragment實現導航欄可以使用很少的程式碼實現很棒的效果。

首先說說TabLayout,它是在Android5.0之後提出的,可以實現Material Design效果,可以方便地幫助我們實現導航欄的效果。接著說一下ViewPager,它是Android擴充套件包v4中的類,可以實現view的左右切換。Fragment就不過多介紹了,相信大家都瞭解。下面就說說具體的實現步驟:

一、實現頂部導航欄

1 . 新增所需依賴

compile 'com.android.support:appcompat-v7:24.2.0'
compile 'com.android.support:design:24.2.0'

說明:上面的第一個包我們在建立Android工程的時候一般會預設引入,他其中包含了Android support v4的包,我們此處是使用v4包中的ViewPager。下面的那個包是我們要使用其中的TabLayout。

2 . 建立對應於每個Tab選項卡的Fragment

接著我們建立對應於每個Tab的View頁面,假設你需要3個Tab,則對應建立3個Fragment檔案,並生成每個Fragment對應的佈局檔案。此處寫一個作為示例。

Fragment1.java

public class Fragment1 extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment1,container, false);
    }
}

fragment1.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</RelativeLayout>

3 . 定義介面卡

接著我們要開始定義介面卡類,為下一步的繫結做準備。

public class MyFragmentPagerAdapter extends FragmentPagerAdapter {
    private String[] mTitles = new String[]{"Fragment1", "Fragment2"};

    public HomeFragmentPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        //此處根據不同的position返回不同的Fragment
        if (position == 1){
            return new Fragment2();
        }
        return new Fragment1();
    }

    @Override
    public int getCount() {
        //此處返回Tab的數目
        return mTitles.length;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        //此處返回每個Tab的title
        return mTitles[position];
    }
}

上面的程式碼很好理解,這裡不再解釋。

4 . 建立主佈局檔案

由於我們要實現的是頂部導航欄,所有我們此處的佈局應該為上面部分是TabLayout,下面部分是ViewPager,佈局檔案如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_role"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@color/colorGray">
    <android.support.design.widget.TabLayout
        app:tabGravity="fill"
        android:id="@+id/home_tablayout"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:background="@color/colorWhite"
        app:tabIndicatorColor="#66ff33"
        app:tabIndicatorHeight="2dp"
        app:tabTextColor="@color/colorTheme"
        app:tabSelectedTextColor="#CC33FF"
        app:tabMode="fixed"
        app:tabBackground="@drawable/tablayout_selector"
        app:tabTextAppearance="@style/TabLayoutTextAppearance">
    </android.support.design.widget.TabLayout>
    <android.support.v4.view.ViewPager
        android:id="@+id/home_viewpager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

    </android.support.v4.view.ViewPager>
</LinearLayout>

上面ViewPager的使用沒什麼好說的,主要是說說TabLayout的一些屬性:

屬性 作用
tabGravity fill 多個tab會平分TabLayout來顯示 / center 多個tab會按實際大小在TabLayout上居中顯示
tabIndicatorColor tab上面指示器的顏色
tabIndicatorHeight tab上面指示器的高度
tabTextColor tab上面顯示的字型的顏色
tabSelectedTextColor tab被選中時字型的顏色
tabMode fixed TabLayout上多個tab是固定的 / scrollable 多個tab時,tab是可以滾動的

注意:這是我踩過的一個坑,當時我把 tabMode設定為scrollable,然後發現tabGravity設定為fill,可是tab還是不能平分TabL,後來才知道,只有tabMode設定為fixed時,tabGravity設定為fill才會生效。

上面的tabBackground我是使用自定義的一個selector實現tab在選中和未選中狀態的背景顏色,下面是程式碼

tablayout_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="true"
        android:drawable="@color/colorTheme"/>
    <item android:drawable="@color/colorGray"/>
</selector>

tabTextAppearance屬性是自己簡單定義的一個文字樣式,主要是設定字型大小及顏色,下面是程式碼:
style.xml檔案

<style name="TabLayoutTextAppearance" parent="TextAppearance.AppCompat.Widget.ActionBar.Title">
        <item name="android:textSize">15sp</item>
        <item name="android:textColor">@color/colorTextGray</item>
</style>

5 . 在MainActivity中繫結佈局

private TabLayout mTabLayout;
private ViewPager mViewPager;
private MyFragmentPagerAdapter mFragmentPagerAdapter;

private TabLayout.Tab mTab1;
private TabLayout.Tab mTab2;

mViewPager = (ViewPager) findViewById(R.id.m_viewpager);
mFragmentPagerAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager());
//給ViewPager設定介面卡
mViewPager.setAdapter(mFragmentPagerAdapter);
//tablayout與Viewpager繫結
mTabLayout = (TabLayout) findViewById(R.id.m_tablayout);
mTabLayout.setupWithViewPager(mViewPager);

mTab1 = mTabLayout.getTabAt(0);
mTab = mTabLayout.getTabAt(1);

通過上面的設定,就可以實現頂部導航欄啦。
下面放上一個效果圖:
這裡寫圖片描述

這裡寫圖片描述
二、實現底部導航欄

其實,底部導航欄非常好實現,我們只需要在佈局檔案中,將上面的部分放置ViewPager,下面的部分放置TabLayout即可,其他內容不變。或許我們有時候需要在底部導航欄加入小圖示,那我們就可以在上面的基礎上通過以下程式碼進行設定:

mTab1.setIcon(R.drawable.ic_1);
mTab2.setIcon(R.drawable.ic_2);

有時候我們可能並不希望我們的ViewPager是可滑動切換的,只希望它可以點選切換,那我們可以通過自定義ViewPager,同時讓其不再攔截觸控事件即可,程式碼如下:

public class DisabledTouchViewPager extends ViewPager {
    //true為允許滑動手勢
    private boolean enable = false;

    public DisabledTouchViewPager(Context context) {
        super(context);
    }

    public DisabledTouchViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return enable;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return enable;
    }
}

然後將xml檔案中的ViewPager換成我們自定義的ViewPager即可。記得必須使用自定義ViewPager的完整路徑。