如何更改 TabLayout 的选定选项卡的图标颜色?

我正在使用一个 TabLayout和一个 ViewPager,我想知道我如何才能最有效地改变颜色的图标的选择标签在 TabLayout。

关于如何实现这一点的完美参考是 谷歌的 Youtube 应用程序。在主页上,有四个图标是深灰色的。当选择一个特定的选项卡时,该选项卡的图标变为白色。

如果没有任何第三方库 ,我怎样才能达到同样的效果呢?

一个可能的解决方案显然是使用选择器。但是在这种情况下,我必须同时找到一个白色和灰色的图标版本,然后在选项卡被选中或取消选择时切换图标。我想知道是否有一个更有效的方法,我可以只突出图标的颜色或东西。我在任何教程中都找不到这个。

剪辑

我在上面直接提到的解决方案需要为每个选项卡的图标使用两个绘图工具。我想知道是否有一种方法,我可以做到这一点与 编程为每个标签的图标可绘制。

97375 次浏览

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.

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" />

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)-->

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">&#xf1ec;</string>
<string name="ic_bank">&#xf19c;</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>

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);
}
}
);
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!

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

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>

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.

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) {


}
});

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) {
}
});

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"

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) {


}
});

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>

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"

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>

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.

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));
}