前言
前面介紹了TabLayout的基本屬性和基本的使用方法。我是傳送門。
真實的業務場景中,很多的效果,原生的TabLayout,並不支持。例如下滑線短於文字的效果,底部導航欄效果,標簽文字選中是需要加粗效果等等。
所以我們需要使用TabLayout的自定義tab標簽。
先上圖。
先為急用的朋友上代碼,后面做講解
java類
import android.content.Context; import android.os.Bundle; import android.support.design.widget.TabLayout; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; import android.view.LayoutInflater; import android.view.View; import android.widget.CheckBox; import java.util.ArrayList; import java.util.List; import butterknife.BindView; import butterknife.ButterKnife; public class MainActivity extends AppCompatActivity { @BindView(R.id.vp_all) ViewPager vpAll; @BindView(R.id.tab_custom) TabLayout tabCustom; //存放自定義tab標簽的列表 List<View> customTabList = new ArrayList<>(); //存放對應tab標簽的fragment頁面 List<PageFragment> fgList = new ArrayList<>(); //選中的自定義標簽,標記器。默認選中第一個。標記位是0; int indicator = 0; ViewPagerAdapter pagerAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this);//此處是用的是butterKnife框架,等同於findviewbyid獲取各個控件。 initTabCustomAndViewPager(); initListener(); } /** * 初始化tab標簽和viewpager內容。 */ private void initTabCustomAndViewPager() { //初始化10個自定義tab標簽 for (int i = 0; i < 10; i++) { final View tabView = getCustomTabView(this, "自定義" + i); customTabList.add(tabView); if (i==0){ //設置默認第一個選中效果 ((CheckBox) tabView.findViewById(R.id.cb_name)).setChecked(true); tabView.findViewById(R.id.cb_slide).setVisibility(View.VISIBLE); } tabCustom.addTab(tabCustom.newTab().setCustomView(tabView)); } //初始化10個fragment頁面 for (int i = 0; i < 10; i++) { fgList.add(PageFragment.newInstance("我是內容欄目" + i)); } pagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(), fgList); vpAll.setAdapter(pagerAdapter); } /** * 將viewpager和tabLayout之間的滑動事件和點擊事件關聯起來。 * 此處不能使用tabLayout的setupWithViewPager()方法,否則會造成自定義view失效 */ private void initListener() { //添加關聯接口,此處不能用自帶的綁定方法,否則自定義view會失效 vpAll.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int i, float v, int i1) { } @Override public void onPageSelected(int i) { tabCustom.getTabAt(i).select(); } @Override public void onPageScrollStateChanged(int i) { } }); tabCustom.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { //viewpager聯動 vpAll.setCurrentItem(tab.getPosition()); //將之前選中的tab標簽,設置為未選中狀態 View oldView = customTabList.get(indicator); CheckBox oldCbName = (CheckBox) oldView.findViewById(R.id.cb_name); View oldCbSlide = oldView.findViewById(R.id.cb_slide); oldCbName.setChecked(false); oldCbSlide.setVisibility(View.INVISIBLE); //當前選中的tab標簽,設置為選中狀態。 indicator = tab.getPosition(); View newView = customTabList.get(indicator); CheckBox newCbName = (CheckBox) newView.findViewById(R.id.cb_name); View newCbSlide = newView.findViewById(R.id.cb_slide); newCbName.setChecked(true); newCbSlide.setVisibility(View.VISIBLE); } @Override public void onTabUnselected(TabLayout.Tab tab) { } @Override public void onTabReselected(TabLayout.Tab tab) { } }); } /** * ViewPager的適配器。 */ class ViewPagerAdapter extends FragmentPagerAdapter { List<PageFragment> fragmentList; public ViewPagerAdapter(FragmentManager fm, List<PageFragment> fragmentList) { super(fm); this.fragmentList = fragmentList; } @Override public Fragment getItem(int position) { return fragmentList.get(position); } @Override public int getCount() { return fragmentList.size(); } } /** * 獲取自定義Tab標簽的顯示的內容 * * @param context * @param * @return */ public static View getCustomTabView(Context context, String text) { View view = LayoutInflater.from(context).inflate(R.layout.item_custom_tab, null); CheckBox tabText = (CheckBox) view.findViewById(R.id.cb_name); tabText.setText(text); return view; } }
pageFragment的代碼和布局就不貼了。不想寫的朋友可以看上一篇:我是傳送門
布局文件
activity_main的布局文件
<?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" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.example.administrator.tablayoutdemo.MainActivity"> <android.support.design.widget.TabLayout android:id="@+id/tab_custom" android:layout_width="match_parent" android:layout_height="wrap_content" app:tabIndicatorHeight="0dp" app:tabMode="scrollable" /> <android.support.v4.view.ViewPager android:id="@+id/vp_all" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
自定義tab標簽的布局文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingLeft="10dp" android:paddingRight="10dp" android:orientation="vertical" android:gravity="center" android:descendantFocusability="blocksDescendants"> <CheckBox android:id="@+id/cb_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:button="@null" android:text="" android:textColor="@drawable/select_text_color" android:textSize="15sp" android:paddingTop="13dp" android:ellipsize="end" android:singleLine="true" android:maxEms="5" android:textStyle="bold" android:paddingBottom="13dp" android:clickable="false" /> <View android:id="@+id/cb_slide" android:layout_width="20dp" android:layout_height="3dp" android:visibility="invisible" android:background="#ff4fbf86"/> </LinearLayout>
色值文件select_text_color,放在drawable目錄下
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="#ff4fbf86" android:state_checked="true"/> <item android:color="#BBBBBB" android:state_checked="false" /> </selector>
講解:
OK上完代碼,針對關鍵點在做一次說明
1、標簽在初始化的過程中,需要對第一個tab標簽提前進行選中狀態的初始化,否則可能會造成第一次啟動的時候,第一個標簽沒有出現選中狀態。
2、viewpager和TabLayout標簽進行聯動的時候,不可以使用TabLayout的setupWithViewPager()方法,而是要通過ViewPager的addOnPageChangeListener()和Tablayout的addOnTabSelectedListener()方法進行兩個控件之間的聯動效果。否則會造成自定義的CustomeTab被TabLayout默認生成的標簽覆蓋掉。
3、在布局文件中,需要將TabLayout的tabIndicatorHeight設為0。用來屏蔽掉控件自動生成的下滑線。
通過自定義的Tab標簽可以完全實現自己控制tab標簽的內容,這里就不展示tab標簽做為底部導航欄的效果了。原理都是一樣的。