1. 程式人生 > >Android進階——Material Design新控制元件之TabLayout製作可滾動的Tabs頁面(二)

Android進階——Material Design新控制元件之TabLayout製作可滾動的Tabs頁面(二)

引言

上一篇總結講解了下TabLayout的基本特點、屬性和簡單的應用步驟,相信大家已經對於TabLayout已經不再陌生,這篇就結合Fragment+ViewPager的架構開發一個主流App的主要框架,進一步學習下TabLayout的操作和監聽,同時分享一些注意事項和非常見錯誤的處理方案。

一、使用TabLayout的專案配置

要使用android.support.design.widget.TabLayout ,需要在自己的工程專案中引入Android的兩個庫android.support.design.widget.TabLayout在Android擴充套件(extras)支援(support)包design中,但是design又依賴另外一個support v7包中的appcompat庫,因此需要事先匯入。

新增依賴包

Android Studio的新增依賴庫很簡單,我只需要在我們Module的build.gradle指令碼檔案中新增如下的(PS:這是使用Android Studio1.4開發的,如果你還使用著Eclipse那麼第一步你應該換成Android Studio)

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:support-v4:23.1.1'
    compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:design:23.1.1' }

二、結合ViewPager+Fragment打造絢麗的Tabs切換頁面

1、首先,還是定義MainActivity的主佈局和Fragment對應的佈局(略)

<?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" xmlns:app="http://schemas.android.com/apk/res-auto" android:orientation="vertical">
<android.support.design.widget.TabLayout android:id="@+id/id_tabLayout" android:layout_width="match_parent" android:layout_height="wrap_content" app:tabMode="scrollable" app:tabGravity="center" /> <android.support.v4.view.ViewPager android:id="@+id/id_viewPager" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:background="#ffffff" /> </LinearLayout>

2、然後初始化ViewPagerAdapter和ViewPager

private ViewPagerAdapter mAdapter;
private List<Fragment> mFragments=new ArrayList<Fragment>();
//初始化ViewPagerAdapter
MainFragment mainTab = new MainFragment();
DiscoveryFragment discTab = new DiscoveryFragment();
Tab3Fragment tab3Fragment=new Tab3Fragment();
Tab4Fragment tab4Fragment=new Tab4Fragment();
Tab5Fragment tab5Fragment=new Tab5Fragment();
Tab6Fragment tab6Fragment=new Tab6Fragment();

mFragments.add(mainTab);
mFragments.add(discTab);
mFragments.add(tab3Fragment);
mFragments.add(tab4Fragment);
mFragments.add(tab5Fragment);
mFragments.add(tab6Fragment);
//初始化ViewPager
mAdapter=new ViewPagerAdapter(getSupportFragmentManager());
mViewPager.setAdapter(mAdapter);

private class ViewPagerAdapter extends FragmentStatePagerAdapter{

        public ViewPagerAdapter(FragmentManager fm) {
            super(fm);
        }
        @Override
        public Fragment getItem(int position) {
            return mFragments.get(position);
        }
        @Override
        public int getCount() {
            return mFragments.size();
        }
        @Override
        public CharSequence getPageTitle(int position) {
            return mTabTitles[position];
        }
    }

3、接著,初始化TabLayout,包括設定一些屬性和新增Tab

private static String[] mTabTitles={"Tab1","Tab2","Tab3","Tab4","Tab5","Tab6"};

mTabLayout.setTabMode(TabLayout.MODE_FIXED);
mTabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
mTabLayout.setBackgroundColor(Color.parseColor("#2b2b2b"));
mTabLayout.setTabTextColors(Color.parseColor("#236f28"), Color.parseColor("#bc6e1c"));mTabLayout.addTab(mTabLayout.newTab().setText(mTabTitles[0]));
mTabLayout.addTab(mTabLayout.newTab().setText(mTabTitles[1]));
mTabLayout.addTab(mTabLayout.newTab().setText(mTabTitles[2]));
mTabLayout.addTab(mTabLayout.newTab().setText(mTabTitles[3]));
mTabLayout.addTab(mTabLayout.newTab().setText(mTabTitles[4]));
mTabLayout.addTab(mTabLayout.newTab().setText(mTabTitles[5]));

4、再把ViewPager和TabLayout管理起來

mTabLayout.setupWithViewPager(mViewPager);//mViewPager必須非null

5、再把ViewPager的介面卡設定到TabLayout上

mTabLayout.setTabsFromPagerAdapter(mAdapter);

6、設定Tab事件監聽

//設定Tab監聽
        mTabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                Log.d("TAG","Selected Tab Index為:"+tab.getPosition());
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {
                Log.d("TAG","Unselected Tab Index為:"+tab.getPosition());
            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {
                Log.d("TAG","Reselected Tab Index為:"+tab.getPosition());
            }
        });

7、完整MainActivity的實現

package com.crazymo.tablayoutviewpager;

import android.graphics.Color;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;


public class MainActivity extends AppCompatActivity {
    private TabLayout mTabLayout;
    private ViewPager mViewPager;
    private ViewPagerAdapter mAdapter;
    private List<Fragment> mFragments = new ArrayList<Fragment>();
    private static String[] mTabTitles = {"Tab1", "Tab2", "Tab3", "Tab4", "Tab5", "Tab6"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
    }

    //初始化
    private void init() {
        getView();
        initTab();
    }

    //找到View
    private void getView() {
        mTabLayout = (TabLayout) findViewById(R.id.id_tabLayout);
        mViewPager = (ViewPager) findViewById(R.id.id_viewPager);
    }

    //初始化Tab
    private void initTab() {
        MainFragment mainTab = new MainFragment();
        DiscoveryFragment discTab = new DiscoveryFragment();
        Tab3Fragment tab3Fragment = new Tab3Fragment();
        Tab4Fragment tab4Fragment = new Tab4Fragment();
        Tab5Fragment tab5Fragment = new Tab5Fragment();
        Tab6Fragment tab6Fragment = new Tab6Fragment();

        mFragments.add(mainTab);
        mFragments.add(discTab);
        mFragments.add(tab3Fragment);
        mFragments.add(tab4Fragment);
        mFragments.add(tab5Fragment);
        mFragments.add(tab6Fragment);
        //設定TabLayout的一系列屬性
        mTabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
        mTabLayout.setBackgroundColor(Color.parseColor("#2b2b2b"));
        mTabLayout.setTabTextColors(Color.parseColor("#236f28"), Color.parseColor("#bc6e1c"));
        mTabLayout.addTab(mTabLayout.newTab().setText(mTabTitles[0]));
        mTabLayout.addTab(mTabLayout.newTab().setText(mTabTitles[1]));
        mTabLayout.addTab(mTabLayout.newTab().setText(mTabTitles[2]));
        mTabLayout.addTab(mTabLayout.newTab().setText(mTabTitles[3]));
        mTabLayout.addTab(mTabLayout.newTab().setText(mTabTitles[4]));
        mTabLayout.addTab(mTabLayout.newTab().setText(mTabTitles[5]));

        mAdapter = new ViewPagerAdapter(getSupportFragmentManager());
        mViewPager.setAdapter(mAdapter);
        mTabLayout.setupWithViewPager(mViewPager);
        mTabLayout.setTabsFromPagerAdapter(mAdapter);

        //設定Tab監聽
        mTabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                Log.e("TAG", "Selected Tab Index為:" + tab.getPosition());
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {
                Log.e("TAG", "Unselected Tab Index為:" + tab.getPosition());
            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {
                Log.e("TAG", "Reselected Tab Index為:" + tab.getPosition());
            }
        });


    }

    private class ViewPagerAdapter extends FragmentStatePagerAdapter {

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

        @Override
        public Fragment getItem(int position) {
            Log.e("TAG", "獲取的Fragement的索引值為:" + position);
            return mFragments.get(position);
        }

        @Override
        public int getCount() {
            return mFragments.size();
        }

        @Override
        public CharSequence getPageTitle(int position) {
            Log.e("TAG", "返回Tab的標題");
            return mTabTitles[position];
        }
    }
}

執行結果

初始化進入到主介面時

這裡寫圖片描述
說明ViewPagerAdapter被執行了兩次
這裡寫圖片描述

滑動TAB1到TAB2時

僅僅觸發的是Tab事件,TAB2到TAB3也是如此。
這裡寫圖片描述

往回滑動TAB3到TAB2時

僅僅觸發的是Tab事件,TAB3返回TAB2也是如此。
這裡寫圖片描述

按主頁鍵之後再返回也並未觸發任何Tab或者ViewPagerAdapter事件,並且還是返回到原來選中的頁面。

這裡寫圖片描述

三、TabLayout的不常見錯誤及處理方案

1、提示res下某些屬性找不到

在匯入庫過程中,如果某些res目錄下的value值過高比如value-23(Android SDK 23)但不巧發生錯誤如提示說找不到某某值,可以整個刪除掉,或者開啟SDK下載最新的相關庫

2、java.lang.NoClassDefFoundError:android.support.v7.internal.widget.TintManager

發生這個或者類似的,包裡的某個類找不到,一般都是因為衝突了,解決辦法之一就是,統一使用支援包的版本比如:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:support-v4:23.1.1'
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.android.support:design:23.1.1'
}

如果還不行就把該工程引入的library moudule的 suppor v4 v7t的版本也改成一致的

3、空指標異常

參照上一篇初始TabLayout的那兩個方法的非空宣告去排查。

public void setupWithViewPager(@NonNull ViewPager viewPager)    //設定與ViewPager關聯起來,注:不允許傳遞空的ViewPager,否則會異常

public void setTabsFromPagerAdapter(@NonNull PagerAdapter adapter)//設定TabLayout的介面卡,注:不允許傳遞空的PagerAdapter,否則會異常

小結

Android Material Design 滑動指示選項卡TabLayout,就是當用戶在該TabLayout的選項卡子item中選擇觸控時候,文字和下方的指示器橫條滑動指示。最後附上完整demo免費下載