9

I've an android project with multiple flavors that I'm working on.

This works fine and I can customize elements of the app such as colors and string resources.

I'm wanting to make it so that some of the flavors are based on the AppCompat light theme and some on the AppCompat dark theme.

I know I could do this by repeating all the <items> in my style and in each flavor setting the theme to point to each one in a custom manifest for each app but that seems overkill.

Is there some easy way to set up a theme as such

    <style name="AppTheme" parent="Theme.AppCompat.NoActionBar">                
            <item name="colorPrimary">@color/primary_colour_tone1</item>
            ...lots more settings
    </style>

But instead of directly pointing to Theme.AppCompat.NoActionBar point to a reference that in each gradle build can be set differently?

So somethings like:

    <style name="AppTheme" parent="**Theme reference here**">                
            <item name="colorPrimary">@color/primary_colour_tone1</item>
            ...lots more settings
    </style>

I've tried using things like @string/theme_name but that doesn't work, is there a simple way to do this?

Mr Lister
  • 45,515
  • 15
  • 108
  • 150
Andrew
  • 7,548
  • 7
  • 50
  • 72

3 Answers3

6

You can define sourceSets for common resources (also sources) for one or more flavors which means you don't have to repeat all resources for all flavors.

For instance, you have 3 flavors. flavor1 and flavor2 uses same theme but flavor3. Then you can define extra source set for common resources, such as commonA (for flavor1, flavor2) and commonB(for flavor3):

...
android {
    ...
    productFlavors {
        flavor1{

        }
        flavor2{

        }
        flavor3{

        }
    }

    sourceSets.flavor1{
        res.srcDirs = ['res', 'src/commonA/res']
    }
    sourceSets.flavor2{
        res.srcDirs = ['res', 'src/commonA/res']
    }
    sourceSets.flavor3{
        res.srcDirs = ['res', 'src/commonB/res']
    }
}

Also you should create the folders src/commanA and src/commonB then put your common resources into their res folders.

Devrim
  • 15,345
  • 4
  • 66
  • 74
  • Thanks, I guess that would still mean having two "style.xml" files both with pretty much the same in them except the "parent" that they inherit. I was hoping for something where that could be more dynamic so as not to have two files with all their settings pretty much identical. – Andrew Dec 03 '15 at 15:38
  • I don't know another solution for your question, I tried some workarounds but no success. I've asked a question, if it gets an answer, yours will be too I guess. http://stackoverflow.com/questions/34110745/is-it-possible-to-define-a-reference-to-theme – Devrim Dec 05 '15 at 21:02
  • at the moment I'm just duplicating the styles twice which works but feels wrong – Andrew Dec 05 '15 at 23:58
6

Just FYI in case anyone is looking for an easy way to do this going forward.

In your manifest, update your theme to something like this...

android:theme="${appTheme}"

Then in your app.gradle do something like this...

productFlavors {
    flavorA{
        manifestPlaceholders = [appTheme: "@style/AppThemeA"]
    }
    flavorB{
        manifestPlaceholders = [appTheme: "@style/AppThemeB"]
    }
}

Then you can use whatever styles you want there and they will tie to the flavor selected.

a54studio
  • 965
  • 11
  • 11
1

better way to create a base style, that contains the default values, then in the main source style and now style extending it (but likely doing nothing). In the flavor you can then extend it and override what you need.

Ajay Keshri
  • 97
  • 1
  • 8
  • 1
    But how do you do that when you want to extend the parent="Theme.AppCompat.NoActionBar" theme? I can't put everything into one theme as it'd then need to extend something (either the light or dark theme) – Andrew Dec 03 '15 at 15:19