How do I change the color of icon of the selected tab of TabLayout?
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.
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);
}
}
);
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.
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) {
}
});
}
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!
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" />