How do I change the color of icon of the selected tab of TabLayout?
JavaAndroidMaterial DesignAndroid TablayoutJava Problem Overview
I'm using a TabLayout
with a ViewPager
and I'm wondering how I can most efficiently change the color of the icon of the selected tab in the TabLayout.
A perfect reference for how this is implemented is Google's Youtube app. On the main page, there are four icons that are colored dark gray. When a specific tab is selected, the tab's icon becomes white.
Without any third party libraries, how can I achieve the same effect?
One possible solution is apparently with selectors. But in that case, I would have to find both a white and a gray version of the icon and then switch the icon when the tab becomes selected or deselected. I'm wondering if there's a more effective method where I can just highlight the icon color or something. I haven't been able to find this in any tutorial.
EDIT
The solution that I mention directly above requires the use of two drawables for each tab's icon. I'm wondering if there's a way I can do it programmatically with ONE drawable for each tab's icon.
Java Solutions
Solution 1 - Java
I found a way that can be easy.
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
tabLayout.setOnTabSelectedListener(
new TabLayout.ViewPagerOnTabSelectedListener(viewPager) {
@Override
public void onTabSelected(TabLayout.Tab tab) {
super.onTabSelected(tab);
int tabIconColor = ContextCompat.getColor(context, R.color.tabSelectedIconColor);
tab.getIcon().setColorFilter(tabIconColor, PorterDuff.Mode.SRC_IN);
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
super.onTabUnselected(tab);
int tabIconColor = ContextCompat.getColor(context, R.color.tabUnselectedIconColor);
tab.getIcon().setColorFilter(tabIconColor, PorterDuff.Mode.SRC_IN);
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
super.onTabReselected(tab);
}
}
);
Solution 2 - Java
This can be done very simply, entirely in xml.
Add one line to your TabLayout in your xml, app:tabIconTint="@color/your_color_selector"
, as below:
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabIconTint="@color/your_color_selector"
app:tabIndicatorColor="@color/selected_color"/>
Then, create a color selector file (named "your_color_selector.xml" above) in res/color directory:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/selected_color" android:state_selected="true"/>
<item android:color="@color/unselected_color"/>
</selector>
This assumes you have 2 colors, "selected_color" and "unselected_color" in your colors.xml file.
Solution 3 - Java
private void setupTabIcons() {
tabLayout.getTabAt(0).setIcon(tabIcons[0]);
tabLayout.getTabAt(1).setIcon(tabIcons[1]);
tabLayout.getTabAt(2).setIcon(tabIcons[2]);
tabLayout.getTabAt(3).setIcon(tabIcons[3]);
tabLayout.getTabAt(0).getIcon().setColorFilter(Color.GREEN, PorterDuff.Mode.SRC_IN);
tabLayout.getTabAt(1).getIcon().setColorFilter(Color.parseColor("#a8a8a8"), PorterDuff.Mode.SRC_IN);
tabLayout.getTabAt(2).getIcon().setColorFilter(Color.parseColor("#a8a8a8"), PorterDuff.Mode.SRC_IN);
tabLayout.getTabAt(3).getIcon().setColorFilter(Color.parseColor("#a8a8a8"), PorterDuff.Mode.SRC_IN);
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
tab.getIcon().setColorFilter(Color.GREEN, PorterDuff.Mode.SRC_IN);
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
tab.getIcon().setColorFilter(Color.parseColor("#a8a8a8"), PorterDuff.Mode.SRC_IN);
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
Solution 4 - Java
You can use a ColorStateList.
First, create an xml file (e.g. /color/tab_icon.xml
) that looks like this and defines the different tints for different states:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/icon_light"
android:state_selected="true" />
<item android:color="@color/icon_light_inactive" />
</selector>
Then add this to your code:
ColorStateList colors;
if (Build.VERSION.SDK_INT >= 23) {
colors = getResources().getColorStateList(R.color.tab_icon, getTheme());
}
else {
colors = getResources().getColorStateList(R.color.tab_icon);
}
for (int i = 0; i < tabLayout.getTabCount(); i++) {
TabLayout.Tab tab = tabLayout.getTabAt(i);
Drawable icon = tab.getIcon();
if (icon != null) {
icon = DrawableCompat.wrap(icon);
DrawableCompat.setTintList(icon, colors);
}
}
First, you grab the ColorStateList from your XML (the method without theme is deprecated, but necessary for pre-Marshmallow devices). Then you set for each tab's icon it's TintList to the ColorStateList; use DrawableCompat (support library) to support older versions as well.
That's it!
Solution 5 - Java
For it You'll have to customize tab icons using selector class for each Tab like:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/advisory_selected" android:state_selected="true" />
<item android:drawable="@drawable/advisory_normal" android:state_selected="false" />
Solution 6 - Java
Add this under res > colors
directory:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:color="@android:color/holo_orange_dark"/>
<item android:color="@android:color/holo_red_light"/>
</selector>
Add code in tab view in xml:
app:tabIconTint="@color/selector_tab"
Solution 7 - Java
Why don't you use icon fonts (like font awesome) for your icons? then change the font of tab text to your desirable font icon .ttf and enjoy change selected text color to your tab icons!
I, myself, used this method and it is really nice and clean :)
firstly, set up the titles from your desired icon font:
in string.xml:
<string name="ic_calculator"></string>
<string name="ic_bank"></string>
then in MainActivity.Java:
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new FragmentBank(), getString(R.string.ic_bank));
adapter.addFragment(new FragmentCalculate(), getString(R.string.ic_calculator));
viewPager.setAdapter(adapter);
}
Then you should change the font of Tab titles to font-awesome:
Typeface typeFaceFont = Typeface.createFromAsset(getAssets(), "fontawesome-webfont.ttf");
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
ViewGroup vg = (ViewGroup) tabLayout.getChildAt(0);
int tabsCount = vg.getChildCount();
for (int j = 0; j < tabsCount; j++) {
ViewGroup vgTab = (ViewGroup) vg.getChildAt(j);
int tabChildsCount = vgTab.getChildCount();
for (int i = 0; i < tabChildsCount; i++) {
View tabViewChild = vgTab.getChildAt(i);
if (tabViewChild instanceof TextView) {
((TextView) tabViewChild).setTypeface(typeFaceFont);
}
}
}
and last but not least, in your related .xml file, set color for your tabTextColor and tabSelectedTextColor:
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="horizontal"
android:background="@color/colorPrimaryDark"
app:tabSelectedTextColor="@color/colorAccent"
app:tabTextColor="@color/textColorPrimary"
app:tabIndicatorColor="@color/colorAccent"
app:tabMode="fixed"
app:tabGravity="fill"/>
</android.support.design.widget.TabLayout>
and in colors.xml:
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
<color name="colorHighlight">#FFFFFF</color>
<color name="textColorPrimary">#E1E3F3</color>
</resources>
Solution 8 - Java
check the following code. Customise your icon one is color and another one is no color.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/mybookings_select" android:state_selected="true"/><!-- tab is selected(colored icon)-->
<item android:drawable="@drawable/mybookings" /><!-- tab is not selected(normal no color icon)-->
Solution 9 - Java
On reference to the second answer which shows how to set color separately, many people might be wondering around how to remove the color of the first icon while switching to next one. What you can do is go like this :
private void setupTabIcons() {
tabLayout.getTabAt(0).setIcon(tabIcons[0]);
tabLayout.getTabAt(1).setIcon(tabIcons[1]);
tabLayout.getTabAt(2).setIcon(tabIcons[2]);
tabLayout.getTabAt(3).setIcon(tabIcons[3]);
tabLayout.getTabAt(0).getIcon().setColorFilter(Color.GREEN, PorterDuff.Mode.SRC_IN);
tabLayout.getTabAt(1).getIcon().setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN);
tabLayout.getTabAt(2).getIcon().setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN);
tabLayout.getTabAt(3).getIcon().setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN);
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
tab.getIcon().setColorFilter(Color.GREEN,PorterDuff.Mode.SRC_IN);
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
//for removing the color of first icon when switched to next tab
tablayout.getTabAt(0).getIcon().clearColorFilter();
//for other tabs
tab.getIcon().clearColorFilter();
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});}
I would have commented on the second answer but did not have enough reputations for that! Sorry. But please follow that you'd save your time and your headache! Happy learning
Solution 10 - Java
You can use addOnTabSelectedListener
, it works for me.
tablayout = findViewById(R.id.viewall_tablayout);
pager = findViewById(R.id.viewall_pager);
adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragments(new RestFragment(),"Restaurant");
adapter.addFragments(new BarFragment(),"Bar");
adapter.addFragments(new HotelFragment(),"Hotel");
adapter.addFragments(new CoffeeFragment(),"Coffee Shop");
pager.setAdapter(adapter);
tablayout.setupWithViewPager(pager);
tablayout.getTabAt(0).setIcon(R.drawable.ic_restaurant);
tablayout.getTabAt(1).setIcon(R.drawable.ic_glass_and_bottle_of_wine);
tablayout.getTabAt(2).setIcon(R.drawable.ic_hotel_black_24dp);
tablayout.getTabAt(3).setIcon(R.drawable.ic_hot_coffee);
tablayout.getTabAt(0).getIcon().setTint(getResources().getColor(R.color.colorAccent,getTheme()));
tablayout.getTabAt(1).getIcon().setTint(getResources().getColor(R.color.colorAccent,getTheme()));
tablayout.getTabAt(2).getIcon().setTint(getResources().getColor(R.color.colorAccent,getTheme()));
tablayout.getTabAt(3).getIcon().setTint(getResources().getColor(R.color.colorAccent,getTheme()));
tablayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
tab.getIcon().setTint(getResources().getColor(R.color.colorPrimary,getTheme()));
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
tab.getIcon().setTint(getResources().getColor(R.color.colorAccent,getTheme()));
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
Solution 11 - Java
For change tint even you can set same color what ever you drawble tab icon have
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
android:background="@color/bgFrag"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:layout_gravity="bottom"
app:tabGravity="fill"
app:tabTextColor="@drawable/tab_search_text_clr"
app:tabIconTintMode="multiply"
app:tabIconTint="#ffffff"
app:tabIndicator="@null"
app:tabTextAppearance="@android:style/TextAppearance.Widget.TabWidget"
app:tabInlineLabel="true"
app:tabMode="fixed" >
</com.google.android.material.tabs.TabLayout>
>tab_search_text_clr.xml
<?xml version="1.0" encoding="utf-8" ?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:color="#ffffff"/> <!-- checked -->
<item android:state_selected="true" android:color="#ffffff"/> <!-- checked -->
<item android:color="#acacac"/><!-- anything else -->
</selector>
Solution 12 - Java
One possible way of "Highlighting" the icon is to access the image view and set the color filter. Try using the setColorFilter(int color) ImageView method and applying the color white.
Solution 13 - Java
tabLayout.setOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager) {...}
Has been deprecated. Rather Use
tabLayout.addOnTabSelectedListener(new TabLayout.BaseOnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
int tabIconColor = ContextCompat.getColor(context, R.color.tabSelectedIconColor);
tab.getIcon().setColorFilter(tabIconColor, PorterDuff.Mode.SRC_IN);
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
int tabIconColor = ContextCompat.getColor(context, R.color.tabUnselectedIconColor);
tab.getIcon().setColorFilter(tabIconColor, PorterDuff.Mode.SRC_IN);
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
Solution 14 - Java
The ColorStateList
only has two entries: android.R.attr.state_selected
and the default wildcard. These can be defined eg. with src/main/res/xml/tab_layout_color_state.xml
:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/colorAccent" android:state_selected="true"/>
<item android:color="@color/white"/>
</selector>
Then R.xml.tab_layout_color_state
can be applied as a ColorStateList
:
private void applyColorStateList(@NonNull TabLayout tabLayout, int resId) {
tabLayout.setTabIconTint(requireContext().getColorStateList(resId));
}
Solution 15 - Java
I know this is a bit old, but I was just facing the same issue and it seems that the answers here are outdated.
Use a color state list and add it directly to the TabLayout XML element
Given the tab_icon.xml file below:-
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/colorPrimary" android:state_selected="true" />
<item android:color="@android:color/darker_gray" />
</selector>
And the TabLayout XML element (notice the tabIconTint attr)
<com.google.android.material.tabs.TabLayout
android:id="@+id/favourites_selectionTL"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tabIconTint="@color/tab_icon"
app:tabIndicatorColor="@color/colorPrimary"
app:tabInlineLabel="true"
app:tabSelectedTextColor="@color/colorPrimary" />
That's it.
Solution 16 - Java
Extending my prefered answer with the ColorStateList from here, you can use the following solution if you are using custom tabs.
Set up tabs in your activity's xml
...
<android.support.design.widget.TabLayout
android:id="@+id/main_tablayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout="@layout/nav_bar_tab_item"/>
<android.support.design.widget.TabItem
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout="@layout/nav_bar_tab_item"/>
</android.support.design.widget.TabLayout>
...
And custom tab layout nav_bar_item.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
android:id="@+id/nav_bar_item_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingEnd="@dimen/_5sdp"
android:paddingStart="@dimen/_5sdp">
<ImageView
android:id="@+id/item_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="@+id/item_description"
android:layout_width="wrap_content"
android:gravity="center"
<!-- Use selector here to change the text color when selected/unselected -->
android:textColor="@color/nav_bar_icons_color"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/item_img"/>
</android.support.constraint.ConstraintLayout>
In your activity
tabLayout = findViewById(R.id.main_tablayout);
ConstraintLayout navMyHotelLayout = (ConstraintLayout) tabLayout.getTabAt(0)
.getCustomView();
tab1Icon = navMyHotelLayout.findViewById(R.id.item_img);
tab1TextView = navMyHotelLayout.findViewById(R.id.item_description);
tab1Icon.setImageResource(R.drawable.ic_tab1);
// Use the selector here to change the color when selected/unselected
tintImageViewSelector(tab1Icon, R.color.nav_bar_icons_color);
tab1TextView.setText("tab 1");
ConstraintLayout navTtdLayout = (ConstraintLayout) tabLayout.getTabAt(1)
.getCustomView();
tab2Icon = navTtdLayout.findViewById(R.id.item_img);
tab2View = navTtdLayout.findViewById(R.id.item_description);
tab2Icon.setImageResource(R.drawable.ic_tab2);
tintImageViewSelector(tab2Icon, R.color.nav_bar_icons_color);
tab2TextView.setText("tab 2");
And add these helper functions for the change of color
public static void tintDrawableSelector(Drawable vd, final @ColorRes int clrRes, Context context) {
DrawableCompat.setTintList(vd, ContextCompat.getColorStateList(context, clrRes));
}
public static void tintImageViewSelector(ImageView imgView, final @ColorRes int clrRes, Context context) {
tintDrawableSelector(imgView.getDrawable(), clrRes);
}
Finally, the selector nav_bar_icons_color.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@android:color/white" android:state_checked="true"/>
<item android:color="@android:color/white" android:state_selected="true"/>
<item android:color="@android:color/black"/>
</selector>
Solution 17 - Java
Check the following code:
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
if(tab.getPosition() == 0){
tabLayout.getTabAt(0).setIcon(tabIcons1[0]);
}
if(tab.getPosition() == 1){
tabLayout.getTabAt(1).setIcon(tabIcons1[1]);
}
if(tab.getPosition() == 2){
tabLayout.getTabAt(2).setIcon(tabIcons1[2]);
}
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
tabLayout.getTabAt(0).setIcon(tabIcons[0]);
tabLayout.getTabAt(1).setIcon(tabIcons[1]);
tabLayout.getTabAt(2).setIcon(tabIcons[2]);
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
Solution 18 - Java
You can change the text color of selected tab using the following xml attribute of Tab layout :
app:tabSelectedTextColor="your desired color"
To customize your icon color of selected tab you need to use selector Create a xml file under drawable folder:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="selected_item_color" android:state_activated="true" />
<item android:color="unselected_item_color" />
</selector>
and add this selector to tab layout xml attribute like below:
app:tabIconTint="@drawable/name_of_file"
Solution 19 - Java
Perform the following steps respectively.
app/src/main/res/values/colors.xml (Add to colors.xml)
<color name="icon_enabled">#F3D65F</color>
<color name="icon_disabled">#FFFFFF</color>
app/src/main/res/color/custom_tab_icon.xml (Create a folder named color in res. Create a custom tab icon.xml in the folder.)
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/icon_enabled" android:state_selected="true"/>
<item android:color="@color/icon_disabled" android:state_selected="false"/>
</selector>
app/src/main/res/drawable/ic_action_settings.png (Create)
double click on action_settings to add
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="21.6"
android:viewportHeight="21.6"
android:tint="@color/custom_tab_icon">
<group android:translateX="-1.2"
android:translateY="-1.2">
<path
android:fillColor="#FF000000"
android:pathData="M19.1,12.9a2.8,2.8 0,0 0,0.1 -0.9,2.8 2.8,0 0,0 -0.1,-0.9l2.1,-1.6a0.7,0.7 0,0 0,0.1 -0.6L19.4,5.5a0.7,0.7 0,0 0,-0.6 -0.2l-2.4,1a6.5,6.5 0,0 0,-1.6 -0.9l-0.4,-2.6a0.5,0.5 0,0 0,-0.5 -0.4H10.1a0.5,0.5 0,0 0,-0.5 0.4L9.3,5.4a5.6,5.6 0,0 0,-1.7 0.9l-2.4,-1a0.4,0.4 0,0 0,-0.5 0.2l-2,3.4c-0.1,0.2 0,0.4 0.2,0.6l2,1.6a2.8,2.8 0,0 0,-0.1 0.9,2.8 2.8,0 0,0 0.1,0.9L2.8,14.5a0.7,0.7 0,0 0,-0.1 0.6l1.9,3.4a0.7,0.7 0,0 0,0.6 0.2l2.4,-1a6.5,6.5 0,0 0,1.6 0.9l0.4,2.6a0.5,0.5 0,0 0,0.5 0.4h3.8a0.5,0.5 0,0 0,0.5 -0.4l0.3,-2.6a5.6,5.6 0,0 0,1.7 -0.9l2.4,1a0.4,0.4 0,0 0,0.5 -0.2l2,-3.4c0.1,-0.2 0,-0.4 -0.2,-0.6ZM12,15.6A3.6,3.6 0,1 1,15.6 12,3.6 3.6,0 0,1 12,15.6Z"/>
</group>
</vector>