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免費下載。