TabLayout我們再熟悉不過了,在開發中,像這種tab切換的需求都會用到TabLayout,它是由官方提供的一個控制元件,在support design 包中。使用起來非常簡單方便,互動效果也很不錯,能滿足我們開發中95%的需求。但是它有一個缺陷:不能改變Tab下劃線(Indicator)的寬度。本篇文章給你帶來改變Tab下劃線寬度的幾種方式:
1 . 通過反射設定Tab下劃線的寬度
2 . 通過TabLayout setCustomView 的方式
3 . 使用第三方開源庫。
複製程式碼
一、通過反射的方式,改變TabLayout下劃線的寬度
首先我們看一下原生的TabLayout的效果(沒有任何修改):
gif演示:
上圖第一個固定模式(tabMode:fixed),下面是滾動模式(tabMode:scrollable),可以看到,所有Tab下方的線(即Indicator)是一樣長的,不管Tab的內容是長還是短。Tab indicator的長度與最長的Tab保持一致。
TabLayout提供了tabIndicatorHeight
屬性來設定indicator的高度,但是沒有提供設定寬度的的api,要想改變indicator的寬度,就得去看看原始碼indicator是怎麼實現的。簡單的看一下原始碼:
如上思維導圖,其中有兩個重點的東西, TabView
和 SlidingTabStrip
,TabView
就是我們所看到的Tab,SlidingTabStrip
是TabView
的父容器,繼承自LinearLayout
,用來處理Tab滑動相關操作,如動畫,繪製Indicator等。
我們要研究indicator是怎麼新增的,重點就在SlidingTabStrip
裡了,這裡我們看到了mSelectedIndicatorHeight
,這就是我們設定Indicator的高度,在draw
方法裡有如下程式碼:
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
// Thick colored underline below the current selection
if (mIndicatorLeft >= 0 && mIndicatorRight > mIndicatorLeft) {
canvas.drawRect(mIndicatorLeft, getHeight() - mSelectedIndicatorHeight,
mIndicatorRight, getHeight(), mSelectedIndicatorPaint);
}
}
複製程式碼
這就是繪製的選中Tab的Indicator,高度是mSelectedIndicatorHeight
,寬是mIndicatorRight - mIndicatorLeft 。那麼者兩個值是從哪兒來的呢?在updateIndicatorPosition
方法中:
private void updateIndicatorPosition() {
// 選中的TabView
final View selectedTitle = getChildAt(mSelectedPosition);
int left, right;
if (selectedTitle != null && selectedTitle.getWidth() > 0) {
// left 和right 的值
left = selectedTitle.getLeft();
right = selectedTitle.getRight();
if (mSelectionOffset > 0f && mSelectedPosition < getChildCount() - 1) {
// Draw the selection partway between the tabs
View nextTitle = getChildAt(mSelectedPosition + 1);
left = (int) (mSelectionOffset * nextTitle.getLeft() +
(1.0f - mSelectionOffset) * left);
right = (int) (mSelectionOffset * nextTitle.getRight() +
(1.0f - mSelectionOffset) * right);
}
} else {
left = right = -1;
}
// 設定mIndicatorLeft和mIndicatorRight
setIndicatorPosition(left, right);
}
void setIndicatorPosition(int left, int right) {
if (left != mIndicatorLeft || right != mIndicatorRight) {
// If the indicator's left/right has changed, invalidate
mIndicatorLeft = left;
mIndicatorRight = right;
ViewCompat.postInvalidateOnAnimation(this);
}
}
複製程式碼
從上面的程式碼就可以看出,Indicator(Tab選中下劃線)的寬度其實就是TabView的寬度,那麼TabView的寬度是多少呢?在SlidingTabStrip
的onMeasure
方法中,為TabView設定了寬度。 請看程式碼:
@Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
...
//以上省略
if (mMode == MODE_FIXED && mTabGravity == GRAVITY_CENTER) {
final int count = getChildCount();
// First we'll find the widest tab
//google的工程師註釋寫的非常清楚:第一步,找出寬度最長的Tab
int largestTabWidth = 0;
for (int i = 0, z = count; i < z; i++) {
View child = getChildAt(i);
if (child.getVisibility() == VISIBLE) {
largestTabWidth = Math.max(largestTabWidth, child.getMeasuredWidth());
}
}
if (largestTabWidth <= 0) {
// If we don't have a largest child yet, skip until the next measure pass
return;
}
final int gutter = dpToPx(FIXED_WRAP_GUTTER_MIN);
boolean remeasure = false;
if (largestTabWidth * count <= getMeasuredWidth() - gutter * 2) {
// If the tabs fit within our width minus gutters, we will set all tabs to have
// the same width
// 第二步:將所有Tab的寬度都設定為largestTabWidth
for (int i = 0; i < count; i++) {
final LinearLayout.LayoutParams lp =
(LayoutParams) getChildAt(i).getLayoutParams();
if (lp.width != largestTabWidth || lp.weight != 0) {
lp.width = largestTabWidth;
lp.weight = 0;
remeasure = true;
}
}
} else {
// If the tabs will wrap to be larger than the width minus gutters, we need
// to switch to GRAVITY_FILL
mTabGravity = GRAVITY_FILL;
updateTabViews(false);
remeasure = true;
}
...
//以下省略
}
}
複製程式碼
這個方法很簡單,一看就明白,有兩個步驟:
1, 一個for迴圈,找出寬度最大的一個TabView
2, 再一個for 迴圈,設定所有TabView的寬度為最長那個TabView的寬度,即largestTabWidth
複製程式碼
這就知道為什麼前面提到的所有Tab 一樣寬,不管長的還是短的。
另外一個點: 上面的
onMeasure
中,執行的條件是mMode == MODE_FIXED && mTabGravity == GRAVITY_CENTER
,如果是其他條件,請看updateTabViews
:
void updateTabViews(final boolean requestLayout) {
for (int i = 0; i < mTabStrip.getChildCount(); i++) {
View child = mTabStrip.getChildAt(i);
child.setMinimumWidth(getTabMinWidth());
updateTabViewLayoutParams((LinearLayout.LayoutParams) child.getLayoutParams());
if (requestLayout) {
child.requestLayout();
}
}
}
複製程式碼
private void updateTabViewLayoutParams(LinearLayout.LayoutParams lp) {
if (mMode == MODE_FIXED && mTabGravity == GRAVITY_FILL) {
lp.width = 0;
lp.weight = 1;
} else {
lp.width = LinearLayout.LayoutParams.WRAP_CONTENT;
lp.weight = 0;
}
}
複製程式碼
如果是MODE_FIXED,並且GRAVITY_FILL,則設定weight=1,所有TabView平分螢幕寬度,MODE_SCROLLABLE ,設定的WRAP_CONTENT
。
反射改變下劃線寬度
思路:知道了繪製Indicator的寬度是根據TabView
的寬度來決定的,那麼我們設定TabView
的寬度就能改變indicator的寬,TabView
的寬由其中的mTextView
決定,因此,通過反射得到mTextView
,設定它的寬度,就能改變Indicator的寬度,這也是網上看到的大多數的解決方法。
上程式碼:
public static void setTabWidth(final TabLayout tabLayout, final int padding){
tabLayout.post(new Runnable() {
@Override
public void run() {
try {
//拿到tabLayout的mTabStrip屬性
LinearLayout mTabStrip = (LinearLayout) tabLayout.getChildAt(0);
for (int i = 0; i < mTabStrip.getChildCount(); i++) {
View tabView = mTabStrip.getChildAt(i);
//拿到tabView的mTextView屬性 tab的字數不固定一定用反射取mTextView
Field mTextViewField = tabView.getClass().getDeclaredField("mTextView");
mTextViewField.setAccessible(true);
TextView mTextView = (TextView) mTextViewField.get(tabView);
tabView.setPadding(0, 0, 0, 0);
//因為我想要的效果是 字多寬線就多寬,所以測量mTextView的寬度
int width = 0;
width = mTextView.getWidth();
if (width == 0) {
mTextView.measure(0, 0);
width = mTextView.getMeasuredWidth();
}
//設定tab左右間距 注意這裡不能使用Padding 因為原始碼中線的寬度是根據 tabView的寬度來設定的
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) tabView.getLayoutParams();
params.width = width ;
params.leftMargin = padding;
params.rightMargin = padding;
tabView.setLayoutParams(params);
tabView.invalidate();
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
});
}
複製程式碼
效果圖如下:
提醒:這種方式改變Indicator最短也就Tab內容的寬度,如果設定很短,Tab內容就顯示不下,如下圖:
二、通過TabLayout setCustomView 的方式
第一種通過反射的方式設定Indicator寬度,最短只能Tab內容的寬度,如果設計師要所有選中的Tab下的Indicator都設定一個指定的寬度,這種就不行了。TabLayout可以設定自定義View,可以通過這種方法來達到目的。
1, 將TabLayout 的tabIndicatorHeight 設定為0
2,通過TabLayout 的setCustomView方式新增Tab
3, 在onTabSelected 回撥種,處理Tab選中和未選中的狀態;
4,為了方便使用,封裝成一個通用的View
複製程式碼
首先看佈局:
enhance_tab_layout.xml
:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.TabLayout
android:id="@+id/enhance_tab_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabIndicatorHeight="0dp"
>
</android.support.design.widget.TabLayout>
</FrameLayout>
複製程式碼
Tab item 佈局:tab_item_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tab_item_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="13sp"
android:text="首頁"
android:textColor="#333333"
/>
<View
android:id="@+id/tab_item_indicator"
android:layout_width="30dp"
android:layout_height="2dp"
android:layout_marginTop="5dp"
android:background="@color/colorAccent"
android:visibility="invisible"
/>
</LinearLayout>
複製程式碼
如上,TextView顯示Tab內容,下面的View就是Tab下面的Indicator(下劃線)。 自己定義的View,寬度隨便你改。
新增Tab的時候使用setCustomView 方法:
/**
* 新增tab
* @param tab
*/
public void addTab(String tab){
mTabList.add(tab);
View customView = getTabView(getContext(),tab,mIndicatorWidth,mIndicatorHeight,mTabTextSize);
mCustomViewList.add(customView);
mTabLayout.addTab(mTabLayout.newTab().setCustomView(customView));
}
/**
* 獲取Tab 顯示的內容
*
* @param context
* @param
* @return
*/
public static View getTabView(Context context,String text,int indicatorWidth,int indicatorHeight,int textSize) {
View view = LayoutInflater.from(context).inflate(R.layout.tab_item_layout, null);
TextView tabText = (TextView) view.findViewById(R.id.tab_item_text);
if(indicatorWidth>0){
View indicator = view.findViewById(R.id.tab_item_indicator);
ViewGroup.LayoutParams layoutParams = indicator.getLayoutParams();
layoutParams.width = indicatorWidth;
layoutParams.height = indicatorHeight;
indicator.setLayoutParams(layoutParams);
}
tabText.setTextSize(textSize);
tabText.setText(text);
return view;
}
複製程式碼
然後在onTabSelected中處理狀態:
@Override
public void onTabSelected(TabLayout.Tab tab) {
mViewPager.setCurrentItem(tab.getPosition());
EnhanceTabLayout mTabLayout = mTabLayoutRef.get();
if(mTabLayoutRef!=null){
List<View> customViewList = mTabLayout.getCustomViewList();
if(customViewList == null || customViewList.size() ==0){
return;
}
for (int i=0;i<customViewList.size();i++){
View view = customViewList.get(i);
if(view == null){
return;
}
TextView text = (TextView) view.findViewById(R.id.tab_item_text);
View indicator = view.findViewById(R.id.tab_item_indicator);
if(i == tab.getPosition()){ // 選中狀態
text.setTextColor(mTabLayout.mSelectTextColor);
indicator.setBackgroundColor(mTabLayout.mSelectIndicatorColor);
indicator.setVisibility(View.VISIBLE);
}else{// 未選中狀態
text.setTextColor(mTabLayout.mUnSelectTextColor);
indicator.setVisibility(View.INVISIBLE);
}
}
}
}
複製程式碼
程式碼其實挺簡單的,但是如果專案中多處使用到,都這樣來處理的話,就顯得麻煩,因此,我們通過自定義View的方式將這些程式碼瘋轉成1個通用的TabLayoutView。如下:
EnhanceTabLayout.java
/**
* 對 support Design 包中的TabLayout包裝
* 主要實現功能:更改indicator 的長度
* Created by zhouwei on 2018/5/18.
*/
public class EnhanceTabLayout extends FrameLayout {
private TabLayout mTabLayout;
private List<String> mTabList;
private List<View> mCustomViewList;
private int mSelectIndicatorColor;
private int mSelectTextColor;
private int mUnSelectTextColor;
private int mIndicatorHeight;
private int mIndicatorWidth;
private int mTabMode;
private int mTabTextSize;
public EnhanceTabLayout(@NonNull Context context) {
super(context);
init(context,null);
}
public EnhanceTabLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context,attrs);
}
public EnhanceTabLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context,attrs);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public EnhanceTabLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context,attrs);
}
private void readAttr(Context context,AttributeSet attrs){
TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.EnhanceTabLayout);
mSelectIndicatorColor = typedArray.getColor(R.styleable.EnhanceTabLayout_tabIndicatorColor,context.getResources().getColor(R.color.colorAccent));
mUnSelectTextColor = typedArray.getColor(R.styleable.EnhanceTabLayout_tabTextColor, Color.parseColor("#666666"));
mSelectTextColor = typedArray.getColor(R.styleable.EnhanceTabLayout_tabSelectTextColor,context.getResources().getColor(R.color.colorAccent));
mIndicatorHeight = typedArray.getDimensionPixelSize(R.styleable.EnhanceTabLayout_tabIndicatorHeight,1);
mIndicatorWidth = typedArray.getDimensionPixelSize(R.styleable.EnhanceTabLayout_tabIndicatorWidth,0);
mTabTextSize = typedArray.getDimensionPixelSize(R.styleable.EnhanceTabLayout_tabTextSize,13);
mTabMode = typedArray.getInt(R.styleable.EnhanceTabLayout_tab_Mode,2);
typedArray.recycle();
}
private void init(Context context,AttributeSet attrs){
readAttr(context,attrs);
mTabList = new ArrayList<>();
mCustomViewList = new ArrayList<>();
View view = LayoutInflater.from(getContext()).inflate(R.layout.enhance_tab_layout,this,true);
mTabLayout = view.findViewById(R.id.enhance_tab_view);
// 新增屬性
mTabLayout.setTabMode(mTabMode == 1 ? TabLayout.MODE_FIXED:TabLayout.MODE_SCROLLABLE);
mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
// onTabItemSelected(tab.getPosition());
// Tab 選中之後,改變各個Tab的狀態
for (int i=0;i<mTabLayout.getTabCount();i++){
View view = mTabLayout.getTabAt(i).getCustomView();
if(view == null){
return;
}
TextView text = (TextView) view.findViewById(R.id.tab_item_text);
View indicator = view.findViewById(R.id.tab_item_indicator);
if(i == tab.getPosition()){ // 選中狀態
text.setTextColor(mSelectTextColor);
indicator.setBackgroundColor(mSelectIndicatorColor);
indicator.setVisibility(View.VISIBLE);
}else{// 未選中狀態
text.setTextColor(mUnSelectTextColor);
indicator.setVisibility(View.INVISIBLE);
}
}
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
public List<View> getCustomViewList(){
return mCustomViewList;
}
public void addOnTabSelectedListener (TabLayout.OnTabSelectedListener onTabSelectedListener){
mTabLayout.addOnTabSelectedListener(onTabSelectedListener);
}
/**
* 與TabLayout 聯動
* @param viewPager
*/
public void setupWithViewPager(@Nullable ViewPager viewPager) {
mTabLayout.addOnTabSelectedListener(new ViewPagerOnTabSelectedListener(viewPager,this));
}
/**
* retrive TabLayout Instance
* @return
*/
public TabLayout getTabLayout(){
return mTabLayout;
}
/**
* 新增tab
* @param tab
*/
public void addTab(String tab){
mTabList.add(tab);
View customView = getTabView(getContext(),tab,mIndicatorWidth,mIndicatorHeight,mTabTextSize);
mCustomViewList.add(customView);
mTabLayout.addTab(mTabLayout.newTab().setCustomView(customView));
}
public static class ViewPagerOnTabSelectedListener implements TabLayout.OnTabSelectedListener{
private final ViewPager mViewPager;
private final WeakReference<EnhanceTabLayout> mTabLayoutRef;
public ViewPagerOnTabSelectedListener(ViewPager viewPager,EnhanceTabLayout enhanceTabLayout) {
mViewPager = viewPager;
mTabLayoutRef = new WeakReference<EnhanceTabLayout>(enhanceTabLayout);
}
@Override
public void onTabSelected(TabLayout.Tab tab) {
mViewPager.setCurrentItem(tab.getPosition());
EnhanceTabLayout mTabLayout = mTabLayoutRef.get();
if(mTabLayoutRef!=null){
List<View> customViewList = mTabLayout.getCustomViewList();
if(customViewList == null || customViewList.size() ==0){
return;
}
for (int i=0;i<customViewList.size();i++){
View view = customViewList.get(i);
if(view == null){
return;
}
TextView text = (TextView) view.findViewById(R.id.tab_item_text);
View indicator = view.findViewById(R.id.tab_item_indicator);
if(i == tab.getPosition()){ // 選中狀態
text.setTextColor(mTabLayout.mSelectTextColor);
indicator.setBackgroundColor(mTabLayout.mSelectIndicatorColor);
indicator.setVisibility(View.VISIBLE);
}else{// 未選中狀態
text.setTextColor(mTabLayout.mUnSelectTextColor);
indicator.setVisibility(View.INVISIBLE);
}
}
}
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
// No-op
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
// No-op
}
}
/**
* 獲取Tab 顯示的內容
*
* @param context
* @param
* @return
*/
public static View getTabView(Context context,String text,int indicatorWidth,int indicatorHeight,int textSize) {
View view = LayoutInflater.from(context).inflate(R.layout.tab_item_layout, null);
TextView tabText = (TextView) view.findViewById(R.id.tab_item_text);
if(indicatorWidth>0){
View indicator = view.findViewById(R.id.tab_item_indicator);
ViewGroup.LayoutParams layoutParams = indicator.getLayoutParams();
layoutParams.width = indicatorWidth;
layoutParams.height = indicatorHeight;
indicator.setLayoutParams(layoutParams);
}
tabText.setTextSize(textSize);
tabText.setText(text);
return view;
}
複製程式碼
暴露了一些常用方法和原生TabLayout 的幾個重要屬性,自定義屬性如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="EnhanceTabLayout">
<attr name="tab_Mode" format="enum">
<enum name="mode_fixed" value="1"/>
<enum name="mode_scrollable" value="2"/>
</attr>
<attr name="tabIndicatorColor" format="color"/>
<attr name="tabSelectTextColor" format="color"/>
<attr name="tabTextColor" format="color"/>
<attr name="tabIndicatorHeight" format="dimension"/>
<attr name="tabIndicatorWidth" format="dimension"/>
<attr name="tabTextSize" format="dimension"/>
</declare-styleable>
</resources>
複製程式碼
好了,這樣就封裝了一個可以改變Indicator 寬度的TabLayout,看一下怎麼用,xml佈局如下:
<com.example.codoon.customtablayout.EnhanceTabLayout
android:id="@+id/enhance_tab_layout"
android:layout_marginTop="30dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabIndicatorHeight="2dp"
app:tabIndicatorWidth="30dp"
app:tabTextColor="#999999"
app:tab_Mode="mode_scrollable"
app:tabSelectTextColor="@color/colorPrimary"
app:tabIndicatorColor="@color/colorPrimary"
app:tabTextSize="6sp"
>
</com.example.codoon.customtablayout.EnhanceTabLayout>
複製程式碼
Activity中程式碼如下:
mEnhanceTabLayout = findViewById(R.id.enhance_tab_layout);
mEnhanceTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
Log.e("log","onTabSelected");
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
for(int i=0;i<sTitle.length;i++){
mEnhanceTabLayout.addTab(sTitle[i]);
}
mEnhanceTabLayout.setupWithViewPager(mViewPager);
List<Fragment> fragments = new ArrayList<>();
for(int i=0;i<sTitle.length;i++){
fragments.add(ItemFragment.newInstance(sTitle[i]));
}
MyAdapter adapter = new MyAdapter(getSupportFragmentManager(),fragments, Arrays.asList(sTitle));
mViewPager.setAdapter(adapter);
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(mEnhanceTabLayout.getTabLayout()));
mEnhanceTabLayout.setupWithViewPager(mViewPager);
複製程式碼
注意,如果是配合ViewPager使用,需要下面兩行程式碼,單獨使用則不需要:
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(mEnhanceTabLayout.getTabLayout()));
mEnhanceTabLayout.setupWithViewPager(mViewPager);
複製程式碼
最後看一下效果:(圖中第二個TabLayout)
三、第三方開源庫
如果前面2中方式都滿足不了你的需求的話,你可以使用第三方庫,也有一些不錯的開源庫,這裡推薦2個。 **1 , MagicIndicator **
github:https://github.com/hackware1993/MagicIndicator star:4.4k
MagicIndicator ,使用方便,還有多種模式可以選擇。包括:
有興趣的可以去試一下。repositories {
...
maven {
url "https://jitpack.io"
}
}
dependencies {
...
compile 'com.github.hackware1993:MagicIndicator:1.5.0'
}
複製程式碼
佈局檔案:
<net.lucode.hackware.magicindicator.MagicIndicator
android:id="@+id/magic_indicator"
android:layout_width="match_parent"
android:layout_height="49dp">
</net.lucode.hackware.magicindicator.MagicIndicator>
複製程式碼
程式碼中:
MagicIndicator magicIndicator = (MagicIndicator) findViewById(R.id.magic_indicator);
CommonNavigator commonNavigator = new CommonNavigator(this);
commonNavigator.setAdapter(new CommonNavigatorAdapter() {
@Override
public int getCount() {
return sTitle == null ? 0 : sTitle.length;
}
@Override
public IPagerTitleView getTitleView(Context context, final int index) {
ColorTransitionPagerTitleView colorTransitionPagerTitleView = new ColorTransitionPagerTitleView(context);
colorTransitionPagerTitleView.setNormalColor(Color.GRAY);
colorTransitionPagerTitleView.setSelectedColor(Color.BLACK);
colorTransitionPagerTitleView.setText(sTitle[index]);
colorTransitionPagerTitleView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mViewPager.setCurrentItem(index);
}
});
return colorTransitionPagerTitleView;
}
@Override
public IPagerIndicator getIndicator(Context context) {
LinePagerIndicator indicator = new LinePagerIndicator(context);
indicator.setMode(LinePagerIndicator.MODE_EXACTLY);
//設定indicator的寬度
indicator.setLineWidth(TabUtils.dp2px(context,20));
return indicator;
}
});
magicIndicator.setNavigator(commonNavigator);
ViewPagerHelper.bind(magicIndicator,mViewPager);
複製程式碼
效果圖如下,圖中最後一個TabLayout:
2 , FlycoTabLayout github:https://github.com/H07000223/FlycoTabLayout star:6.5k
功能和MagicIndicator差不多,都支援多種Indicator效果:
具體使用請看github 詳細介紹。
四、總結
本文總結了改變TabLayout下劃線(indicator)寬度的幾種方式,使用的時候根據自己的需求選擇,在原生控制元件能做的情況下,儘量使用原生控制元件,畢竟匯入三方庫需要一些額外的成本。如果你還有更好的方式,歡迎評論區留言討論。
更多Android乾貨文章,關注公眾號 【Android技術雜貨鋪】