10

Tab Icons: My current method is to create two files (ic_list_selected_24dp.xml and ic_list_unselected_24dp.xml; they are basically the same but only the android:fillColor='Color HEX CODE' are different), and then create a selector (selector_tabitem_list.xml) to change the drawable color when the state is changed.

// @drawable/selector_tabitem_list.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:app="http://schemas.android.com/apk/res-auto">
    <item android:drawable="@drawable/ic_list_selected_24dp" 
        android:state_selected="true" />
    <item android:drawable="@drawable/ic_list_unselected_24dp" 
        android:state_selected="false" />
</selector>

It's kind of duplicated because two drawables are the same.

Selector cannot be used in vector drawable.

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
    <path
        android:fillColor="@drawable/selector"
        android:pathData="M19,3...."
</vector>

--

// @drawable/selector

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="true">
        <color android:color="@color/itemSelected" />
    </item>
    <item android:state_selected="false">
        <color android:color="@color/itemUnselected" />
    </item>
</selector>

, and android:fillColor="@color/state" either.

// @color/state

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@android:color/white" android:state_selected="true" />
    <item android:color="@android:color/black" android:state_selected="false" />
</selector>

Is there any way to use one drawable and change its color dynamically? Using hard hex code is better?

Thanks.

sunadorer
  • 3,855
  • 34
  • 42
cmingmai
  • 239
  • 3
  • 15
  • You can try using `android:drawableTint` for the view – VishnuSP May 08 '17 at 12:06
  • Thanks for the advice, but I use this case for the tab icons. Still use android:drawableTint? It seems to be available in higher version(>=23). What's the difference between 'android:drawableTint' and 'android:Tint'? – cmingmai May 08 '17 at 12:22
  • 3
    I found the soloution. I added `android:tint="@color/tab_state"` in the vector tag. – cmingmai May 08 '17 at 13:23
  • 1
    http://stackoverflow.com/questions/36741036/android-selector-drawable-with-vectordrawables-srccompat/36886237#36886237 – cmingmai May 08 '17 at 14:12

3 Answers3

16

Here is the complete list of steps to use a vector asset as tinted icon in a TabItem (which is part of the support design lib). All parts are present in the original question and linked answer, but are easy to miss.

  1. Create the selector. Note that it has to switch the color for state_selected (as included in the question, but not in the answer linked by @cmingmai. There it only states android:state_enabled which is not relevant for tabs):

res/color/selector_navigation.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="false" android:color="@android:color/black" />
    <item android:state_selected="true" android:color="@android:color/white" />
</selector>
  1. Adjust the vector drawable by adding android:tintMode and android:tint to the vector tag. In addition for the tinting to work with multiply, the fillColor of the path needs to be set to white!

res/drawable/ic_tab_list:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:height="24dp"
        android:width="24dp"
        android:viewportHeight="24.0"
        android:viewportWidth="24.0"
        android:tintMode="multiply"
        android:tint="@color/selector_navigation">
    <path
        android:fillColor="@android:color/white"
        android:pathData="..." />
</vector>
  1. Use vector drawable in Layout – or use to create the tabs in code as shown in the developer guide on Tabs. Note that I also modified the tab indicator color to match the active icon color to follow the material design guidelines.

Relevant part of the layout:

<android.support.design.widget.TabLayout
    android:id="@+id/tabs"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:tabIndicatorColor="@android:color/white">

    <android.support.design.widget.TabItem
        android:id="@+id/tabItem"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:icon="@drawable/ic_tab_list" />
    <!-- More Tabs -->
</android.support.design.widget.TabLayout>
  1. Adjust build.gradle with following to activate vector support for old Android versions (in case it was not already previously added):

    android { defaultConfig { vectorDrawables.useSupportLibrary = true } }

sunadorer
  • 3,855
  • 34
  • 42
  • 1
    Make sure there is no android:tint in your final Widget. This solution worked for me in a ImageButton with app:srcCompat. – BlackCath Jul 17 '18 at 06:41
  • You actually see the icons in the tabLayout without adding them programmatically? I can't get these xml TabItems to show the icons – galaxigirl Jun 08 '19 at 10:18
  • @galaxigirl Yes, I didn't have to add the icons elsewhere. Sry, don't have access to the project from this anymore. But I think the activity only added adapter/listener to handle content switch on tab changes. Can't remember if the layout preview worked but definitely worked when running. Probably best if you get stuck to ask your own question. Could be many different things. e.g. Does your tab bar look like it has the space of the icon or text only? Maybe the icon colour is set to the background? Or double check how you set up the drawable `selector` if required states are there. – sunadorer Jun 10 '19 at 16:27
  • This seems to work nice with androidX appcompat:1.1.0. Just set the fillcolor in the vector drawable to white, and then apply the android:tint selector drawable on the imageview itself. Making it very flexible. – Peterdk Jan 07 '20 at 20:16
0

Upgrade to Support Library 28.0.0+ (presumably same for androidx.. didn't test).

On Support Library 28.0.0 using a selector color xml resource seems to work now when used as vector's android:fillColor.

In fact the previous solution (using vector's android:tintMode, android:tint and white for android:fillColor) no longer works for me on Support Library 28.0.0.

Tested on API 21 and 27 Emulators.

Jimmy Alexander
  • 445
  • 2
  • 9
  • I tried this with androidX appcompat:1.1.0, and it does not work. Setting fillcolor to white and then add android:tint to the imageview works. – Peterdk Jan 07 '20 at 20:14
0

Try replacing the AppTheme in style.xml with a different parent like so:

style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar"

Mitch
  • 1,716
  • 3
  • 25
  • 41