Search code examples
androidandroid-viewandroid-themeandroid-styles

How to set different themes and best way in Android


I have some doubts about this topic.

I have only user the night/day theme that android offers us with their API and you set the theme for both. And then it applies with setNightMode() and everything like that. What I did then was to set a color in a background of a view and it changed when set to night theme

So I was wondering if for example I create 3 themes (Light/Dark/Blue) like this (I don't want to repeat code so I'll show 1 theme):

    <style name="Theme.Blue" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
        <!-- Primary brand color. -->
        <item name="colorPrimary">@color/green</item>
        <item name="colorPrimaryVariant">@color/greentwo</item>
        <item name="colorOnPrimary">@color/reed</item>
        <!-- Secondary brand color. -->
        <item name="colorSecondary">@color/teal_200</item>
        <item name="colorSecondaryVariant">@color/teal_700</item>
        <item name="colorOnSecondary">@color/black</item>
        <!-- Status bar color. -->
        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
        <!-- Customize your theme here. -->
    </style>

And then when I enter into an activity/fragment:

  1. I check what is the preferred theme that user has set and for example the theme see is Theme.Blue

  2. So for this theme I want to load some texts of color green and others text of color red, so my thought is to set the theme programatically. TextView.setAppareance(Theme style) which seems like a really hard work.

And same goes for background where there is a contrast with a higher and lower tone of the same color and etc..

Do I have to inherit any theme, set it on the top of xml or set it 1 by 1 to every view or anything that i don't know?

  • So how could I make this, what is the recommended way?

  • I don't exactly understand where colorPrimary, colorPrimaryVariant and this stuff goes. For example when creating the Alert Dialog the buttons are set on green!

About managing the current user preferences theme is not the problem, the problem is about applying this to all views their styles.


Solution

  • The whole point of having different Themes is not having to change everything programmatically. so you need to have different styles for different themes:

    <resources>
    
    <!-- Base application theme. -->
        <!-- Light theme. -->
        <style name="LightMode" parent="Theme.AppCompat.Light.NoActionBar">
    
            <!-- Customize your theme here. -->
            <item name="colorPrimary">@color/colorPrimary2</item>
            <item name="colorPrimaryDark">@color/colorPrimaryDark2</item>
            <item name="colorAccent">@color/colorAccent2</item>
            <item name="color_text">@color/color_text2</item>
            
        </style>
    
        <!-- Dark theme. -->
        <style name="NightModeTheme" parent="Theme.AppCompat.NoActionBar">
    
            <!-- Customize your theme here. -->
            <item name="colorPrimary">@color/colorPrimary</item>
            <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
            <item name="colorAccent">@color/colorAccent</item>
            <item name="color_text">@color/color_text</item>
    
        </style>
    </resources>
    

    And different attributes as well in your attr.xml:

    <resources>
    
        <declare-styleable name="Theme">
            <attr name="colorPrimary" format="color"/>
            <attr name="colorPrimaryDark" format="color"/>
            <attr name="colorAccent" format="color"/>
            <attr name="color_text" format="color"/>
    
            ...
    
        </declare-styleable>
    </resources
    

    And different color sets like this in your colors.xml:

    <resources>
        <!-- Dark theme colors. -->
        <color name="colorPrimary">#353535</color>
        <color name="colorPrimaryDark">#252525</color>
        <color name="colorAccent">#FF3C00</color>
        <color name="color_text">#FFFFFF</color>
    
        <!-- Light theme colors. -->
        <color name="colorPrimary2">#FFFFFF</color>
        <color name="colorPrimaryDark2">#FFBB29</color>
        <color name="colorAccent2">#FFB728</color>
        <color name="color_text2">#272727</color>
    
    </resources>
    

    And then in your views in the xml file you will get the colors from the attr file not the colors file like this:

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Read me"
        android:textColor="?attr/color_text"/>
    

    Also when you wanna set the theme for every activity, make sure you do it before setting the content view.

    you can have a class like this:

    abstract class ThemeManager {
    
        public static void set(Context context, String activeTheme) {
            int themeRecourseID = R.style.LightMode;
            if (activeTheme.equals("DarkMode")) {
                themeRecourseID = R.style.DarkMode;
            }
            context.setTheme(themeRecourseID);
        }
    }
    

    And use it this way:

    override fun onCreate(savedInstanceState: Bundle?) {
    
        //SET THE THEME HERE BEFORE SETTING THE CONTENTVIEW OF THE ACTIVITY
        ThemeManager.set(this, "DarkMode");
    
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    
    }