How to Change the New Tablayout Indicator Color and Height

How to change the new TabLayout indicator color and height

Having the problem that the new TabLayout uses the indicator color from the value colorAccent, I decided to dig into the android.support.design.widget.TabLayout implementation, finding that there are no public methods to customize this. However I found this style specification of the TabLayout:

<style name="Base.Widget.Design.TabLayout" parent="android:Widget">
<item name="tabMaxWidth">@dimen/tab_max_width</item>
<item name="tabIndicatorColor">?attr/colorAccent</item>
<item name="tabIndicatorHeight">2dp</item>
<item name="tabPaddingStart">12dp</item>
<item name="tabPaddingEnd">12dp</item>
<item name="tabBackground">?attr/selectableItemBackground</item>
<item name="tabTextAppearance">@style/TextAppearance.Design.Tab</item>
<item name="tabSelectedTextColor">?android:textColorPrimary</item>
</style>

Having this style specification, now we can customize the TabLayout like this:

<android.support.design.widget.TabLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@id/pages_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:tabIndicatorColor="@android:color/white"
app:tabIndicatorHeight="4dp"/>

And problem solved, both the tab indicator color and height can be changed from their default values.

How to change Tab Indicator color programmatically

I use Jeff Gilfelt,s Android Action Bar Style Generator. You can use GUI to style your tabs and at the end you get the source code which you can use, review and modify accordingly. :)

Here's a link.

http://jgilfelt.github.io/android-actionbarstylegenerator/#name=example&compat=holo&theme=light&actionbarstyle=solid&texture=0&hairline=0&neutralPressed=1&backColor=E4E4E4%2C100&secondaryColor=D6D6D6%2C100&tabColor=33B5E5%2C100&tertiaryColor=F2F2F2%2C100&accentColor=33B5E5%2C100&cabBackColor=FFFFFF%2C100&cabHighlightColor=33B5E5%2C100

change the selected tab indicator color of TabLayout(android.support.design.widget)

I can't comment so I'll add it here.

Update the Design Support Library and you'll see the setSelectedTabIndicatorColor() method.

This is the line in my build.gradle:

compile 'com.android.support:design:23.1.0'

Android Tab layout: Wrap tab indicator width with respect to tab title

Yes, it's possible to wrap tab indicator as title setting padding to 0

 public void wrapTabIndicatorToTitle(TabLayout tabLayout, int externalMargin, int internalMargin) {
View tabStrip = tabLayout.getChildAt(0);
if (tabStrip instanceof ViewGroup) {
ViewGroup tabStripGroup = (ViewGroup) tabStrip;
int childCount = ((ViewGroup) tabStrip).getChildCount();
for (int i = 0; i < childCount; i++) {
View tabView = tabStripGroup.getChildAt(i);
//set minimum width to 0 for instead for small texts, indicator is not wrapped as expected
tabView.setMinimumWidth(0);
// set padding to 0 for wrapping indicator as title
tabView.setPadding(0, tabView.getPaddingTop(), 0, tabView.getPaddingBottom());
// setting custom margin between tabs
if (tabView.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) tabView.getLayoutParams();
if (i == 0) {
// left
settingMargin(layoutParams, externalMargin, internalMargin);
} else if (i == childCount - 1) {
// right
settingMargin(layoutParams, internalMargin, externalMargin);
} else {
// internal
settingMargin(layoutParams, internalMargin, internalMargin);
}
}
}

tabLayout.requestLayout();
}
}

private void settingMargin(ViewGroup.MarginLayoutParams layoutParams, int start, int end) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
layoutParams.setMarginStart(start);
layoutParams.setMarginEnd(end);
layoutParams.leftMargin = start;
layoutParams.rightMargin = end;
} else {
layoutParams.leftMargin = start;
layoutParams.rightMargin = end;
}
}

Result

EDIT:
As of com.android.support:design:28.0.0, you can adjust the indicator as label easily now setting:

app:tabIndicatorFullWidth="false"

EDIT July 2019:
Use the material dependency
com.google.android.material:material:x.x.x

Changing tab indicator background (for all the tablayout view)

To achieve what you are looking for you can try the following

Create a selector tab_layout_selector

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

<item android:state_selected="false" android:state_pressed="false">

<layer-list>

<!-- Stripe bottom indicator color -->
<item android:top="-5dp" android:left="-5dp" android:right="-5dp">
<shape android:shape="rectangle">
<stroke android:color="@color/red" android:width="4dp"/>
</shape>
</item>

</layer-list>

</item>

</selector>

Finally, in your TabLayout add

 <android.support.design.widget.TabLayout

<!-- Whole tab background -->
android:background="@color/white"

<!-- Line color -->
android:tabBackground="@drawable/tab_layout_selector"

.... Others....
/>

Android TabLayout custom indicator width

Try this.

public void setIndicator (TabLayout tabs,int leftDip,int rightDip){  
Class<?> tabLayout = tabs.getClass();
Field tabStrip = null;
try {
tabStrip = tabLayout.getDeclaredField("mTabStrip");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}

tabStrip.setAccessible(true);
LinearLayout llTab = null;
try {
llTab = (LinearLayout) tabStrip.get(tabs);
} catch (IllegalAccessException e) {
e.printStackTrace();
}

int left = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, leftDip, Resources.getSystem().getDisplayMetrics());
int right = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, rightDip, Resources.getSystem().getDisplayMetrics());

for (int i = 0; i < llTab.getChildCount(); i++) {
View child = llTab.getChildAt(i);
child.setPadding(0, 0, 0, 0);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 1);
params.leftMargin = left;
params.rightMargin = right;
child.setLayoutParams(params);
child.invalidate();
}
}

And then

tab.post(new Runnable() {  
@Override
public void run() {
setIndicator(tab,60,60);
}
});


My modification w/o reflection (custom view should be set!).

for (int i = 0; i < tabs.getTabCount(); i++) {
TabLayout.Tab tab = tabs.getTabAt(i);
if (tab != null) {
View customView = tab.getCustomView();
if (customView != null) {
View targetViewToApplyMargin = (View) customView.getParent();
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) targetViewToApplyMargin.getLayoutParams();

layoutParams.rightMargin = totalTabMargin;
targetViewToApplyMargin.setLayoutParams(layoutParams);
}
}
}


Related Topics



Leave a reply



Submit