Search code examples
androidstylesthemesshared-librariesandroid-attributes

Android Resolving style properties and attributes?


My Android Application has a main Project Module that has the following declaration in the styles file. This Theme is used in the Manifest file on the "application" tag so all components within the "application" element have the same theme applied.

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
    <item name="android:colorPrimary" tools:ignore="NewApi">
        @color/light_black
    </item>
    <item name="colorPrimary">@color/light_black</item>
    <item name="android:colorAccent" tools:ignore="NewApi">@color/sapphire</item>
    <item name="colorAccent">@color/sapphire</item>
    <item name="android:colorBackground">@color/primary_background</item>
    <item name="android:textColorPrimary">@color/title_color</item>
    <item name="android:colorButtonNormal" tools:ignore="NewApi">@color/sapphire</item>
    <item name="colorButtonNormal">@color/sapphire</item>
    <item name="android:colorForeground" tools:ignore="NewApi">
        @color/title_color
    </item>
    <item name="android:titleTextStyle">@style/toolbar_title</item>
    <item name="android:navigationIcon" tools:ignore="NewApi">
        ?android:attr/homeAsUpIndicator</item>
    <item name="navigationIcon">?android:attr/homeAsUpIndicator</item>
    <item name="android:colorControlNormal" tools:ignore="NewApi">@android:color/white</item>
    <item name="colorControlNormal">@android:color/white</item>
</style>

I also have a Library module next to the main Project module, where I will be putting most commonly used Views, Widgets and base-components that can be reused with other applications within my Application Project, or others within the organization. As for Gradle Dependency declaration, the Project Module depends on the Library Module, and not the vice-versa, of course.

How do I resolve "colorAccent" and "colorControlNormal" default android-attributes inside my Library Module components code-base at run-time depending on the Theme of the appropriate Context (Activity instance) in the main Project Module?

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:tools="http://schemas.android.com/tools">
<item android:color="?android:attr/colorControlNormal"
    android:state_activated="false"
    tools:ignore="NewApi"/>

<item android:color="?android:attr/colorAccent"
    android:state_activated="true"
    tools:ignore="NewApi"/>
</selector>

Solution

  • So here's how I fixed this.

    attrs.xml in the Library Module. Notice the format is a "integer", although the attributes are supposedly colors.

    <attr name="progressColorControlNormal" format="reference|integer" />
    <attr name="progressColorAccent" format="reference|integer" />
    

    Because the main Project Module is dependent on the Library Module, I could access these attributes in the Theme definition in the styles.xml file.

    <item name="progressColorControlNormal">@android:color/white</item>
    <item name="progressColorAccent">@color/sapphire</item>
    

    Do notice the resolved values for the colors, and not references from the Theme itself such as "?android:attr/colorControlNormal" and "?android:attr/colorAccent", or their variants.

    The drawable xml in the Library Module now resolves the Themed Colors automatically.

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android" 
        xmlns:tools="http://schemas.android.com/tools">
        <item android:color="?progressColorControlNormal"
            android:state_activated="false"
            tools:ignore="NewApi"/>
    
        <item android:color="?progressColorAccent"
            android:state_activated="true"
            tools:ignore="NewApi"/>
    </selector>