Android Tutorial Changing the theme at runtime

Using the hooks feature it is possible to change the Activity theme at runtime.

The theme is set before the activity is actually shown. This means that in order to change the theme we need to destroy the activity and start it again. You can use StateManager to save the activity state.


The hook code is:
B4X:
#if java
public void _onCreate() {
   if (_theme_value != 0)
     setTheme(_theme_value);
}
#end if
There must be a process global int variable named Theme_Value. Note that the underscore is important. It prevents the obfuscator from changing the variable name which will cause the inline Java code to break.

Updates

Example updated and the selected theme value is stored in a file. The theme is set when the app starts.
 

Attachments

  • ThemeChange.zip
    8.5 KB · Views: 1,649
Last edited:

joneden

Active Member
Licensed User
Longtime User
I found a work around and can set the status bar colour manually. It's a roundabout way of doing it but it still gets the theme colour. If anyone else runs into the same issue use the code below.

B4X:
    Dim objAppCompat As AppCompat
    Dim jo As JavaObject
    jo.InitializeContext
    jo.RunMethodJO("getWindow", Null).RunMethod("setStatusBarColor", Array(objAppCompat.GetThemeAttribute("colorPrimaryDark")))
 

joneden

Active Member
Licensed User
Longtime User
Seems that the issue relates to SDK22 - 23 seems to work fine without any custom work around :)
 

joneden

Active Member
Licensed User
Longtime User
No changing the theme in the manifest editor changes it once, this thread discusses changing the active theme while the app is running.
 

ArminKH

Well-Known Member
I found a work around and can set the status bar colour manually. It's a roundabout way of doing it but it still gets the theme colour. If anyone else runs into the same issue use the code below.

B4X:
    Dim objAppCompat As AppCompat
    Dim jo As JavaObject
    jo.InitializeContext
    jo.RunMethodJO("getWindow", Null).RunMethod("setStatusBarColor", Array(objAppCompat.GetThemeAttribute("colorPrimaryDark")))
can u (or every body)give me the java code of above code?following code doesn't works
B4X:
import android.view.WindowManager;


public class T8Extra {
   
    public void SetStatusBarColor(int Color) {
        if (android.os.Build.VERSION.SDK_INT >= 21) {
           
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            getWindow().setStatusBarColor(Color);
        }
    }
}
tnx
 

fgrdovic21

Member
Licensed User
Longtime User
Hi all

Is it possible to programmatically change the colors of a theme (colorPrimary, colorPrimaryDark, colorAccent) or Toolbar/Statusbar to any color, not to a predefined theme? Or at least, set the opacity of a Statusbar to, perhaps, 10% so it darkens the control underneath.

Thanks
 

ArminKH

Well-Known Member
Hi all

Is it possible to programmatically change the colors of a theme (colorPrimary, colorPrimaryDark, colorAccent) or Toolbar/Statusbar to any color, not to a predefined theme? Or at least, set the opacity of a Statusbar to, perhaps, 10% so it darkens the control underneath.

Thanks
post 22 is exactly what do you want to do
just instead
Array(objAppCompat.GetThemeAttribute("colorPrimaryDark"))
you should use your color like colors.red
 

fgrdovic21

Member
Licensed User
Longtime User
post 22 is exactly what do you want to do
just instead
Array(objAppCompat.GetThemeAttribute("colorPrimaryDark"))
you should use your color like colors.red

Thanks ArminKH, that worked like a charm. I didn't know you can put colors there. Next time, maybe I should check what parameters that method uses :D
I can also confirm you can put transparency and it will brighten or dimmer the statusBar (ARGB(20,0,0,0) for example).
 

trueboss323

Active Member
Licensed User
Longtime User
Is it possible to load a theme that is stored in my ...\Objects\res\values folder?
 
Last edited:

trueboss323

Active Member
Licensed User
Longtime User
I do not mean from the manifest. In my case, I have multiple themes that I want to use. I want to give users the option of what theme they want, and depending on their selection, would load the appropriate theme file.
 
Last edited:

vbmundo

Well-Known Member
Licensed User
Ok,

But if you only need to set a fixed Theme in your activity you can include only this

B4X:
#if java
public void _onCreate() {
    setTheme(16973931);
}
#end if

16973931 = Holo Theme

without finish and recreate the Activity

This works for me..

Regards
 

trueboss323

Active Member
Licensed User
Longtime User
Ok,

But if you only need to set a fixed Theme in your activity you can include only this

B4X:
#if java
public void _onCreate() {
    setTheme(16973931);
}
#end if

16973931 = Holo Theme

without finish and recreate the Activity

This works for me..

Regards

Should I place the different xml files inside \Objects\res\values ? Then how would I load that specific file?
 

vbmundo

Well-Known Member
Licensed User
Should I place the different xml files inside \Objects\res\values ? Then how would I load that specific file?

I don't know, perhaps I'm not the experts that you need, I only simplify the Erel's code (because my APP don't allow users to change the Design) if you see the Erel's code, for every click in diferent buttons, the system retrieve the ID of every theme and apply it.

I only put the ID directly on _onCreate().

This Works for me...
 

silpot

Member
Licensed User
Longtime User
This theme changer works perfect when I try to exit from app by using the phone's back button. I can change the theme from Theme.Holo.Light to Theme.Holo and vice versa.
The problem is that when I kill (close) all running apps from my cell phone, the theme returns to the default one.

Is there any solution to that problem ?
Is there any other solution to let the user change the theme when he wants to ?
 

silpot

Member
Licensed User
Longtime User
Thanks Erel. I already did that. When the app is runing for the first time it reads a stored value and restarts to the desired theme.
The whole process of restarting, creates bad layout transition between the dark and the Light theme

Do you have a functional example to do that better ?
 
Last edited:
Top