Android Tutorial Changing the theme at runtime

Discussion in 'Tutorials & Examples' started by Erel, Aug 16, 2015.

  1. Erel

    Erel Administrator Staff Member Licensed User

    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:
    Code:
    #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.
     

    Attached Files:

    Last edited: Jan 25, 2019
  2. LucaMs

    LucaMs Expert Licensed User

    Just one question (out of laziness, I could search :D):
    The range of values of _theme_value?

    Ah, some themes can not be supported (material)... maybe a Try is sufficient, I think.
     
  3. Erel

    Erel Administrator Staff Member Licensed User

    There is no range. See how the code sets the themes.

    A Try / Catch block is not needed. See the code...
     
    Peter Simpson and LucaMs like this.
  4. LucaMs

    LucaMs Expert Licensed User

  5. ArminKH

    ArminKH Well-Known Member

    woooooooooow great
    thank u erel
     
  6. schimanski

    schimanski Well-Known Member Licensed User

    Much thanks for this tutorial!

    I have two questions:

    1. Is it possible to change the color of the preference-screen at runtime. Now, the preference-screen get the design, which is based on the manifest-file.
    2. Is it possible to check, which design is active?
     
  7. Erel

    Erel Administrator Staff Member Licensed User

    1. It is not possible (without modifying the library).
    2. The selected theme resource id is stored in theme_value variable.
     
    schimanski likes this.
  8. trueboss323

    trueboss323 Active Member Licensed User

    Hi Erel,
    What correct code should I use when saving and loading the activity state?

    And also, the Material themes do not work for me on Android 4.4
     
    Last edited: Sep 15, 2015
  9. Erel

    Erel Administrator Staff Member Licensed User

    Material theme is only available on Android 5+.

    Search for StateManager to see how the state can be handled.
     
  10. chrjak

    chrjak Active Member Licensed User

    Hey Erel,

    How can u access the Process_Global Main value from other modules?
    _theme_value uses the current activity
    and main_theme_value does not work :D

    Normally it should be possible to start every other activity in the theme of the correct main theme value without restarting
     
  11. Erel

    Erel Administrator Staff Member Licensed User

    It should be main._theme_value
     
  12. chrjak

    chrjak Active Member Licensed User

    Thank you :)

    Is it everytime: modulename._theme_value?

    eg. a Module named "Modul1"
    modul1._theme_value
     
  13. Erel

    Erel Administrator Staff Member Licensed User

    Yes.
     
  14. joneden

    joneden Active Member Licensed User

    Hi Erel,
    This is great and I am working with it on my redesign to Material design. I have got two requests, one you should be able to easily tell me how to solve, the second maybe more tricky.

    I save the theme ID into a variable that the statemanager then saves (StateManager.SetSetting("CurrentThemeId", Main.CurrentThemeId)). This works well for activities that are not the initial one. I need to get the data from the CurrentThemeId that is saved into the java _onCreate hook. What java would I need to add in order to get the data from the saved var BEFORE the page loads.

    By using setTheme(2131165536); I have tested and this works so it's just the ID that I need.

    The second issue that I have is re the main status bar changes properly to the colorPrimaryDark value in later activities but the main activity ALWAYS shows the value for the default theme. Any suggestions?

    Regards

    Jon

    Further to the above I have managed to hack the first question by copying out java code from the source files - I'm sure there is a better way of doing it, second question still stands though.

    Code:
    #if java
    public static anywheresoftware.b4a.objects.collections.Map _settings = new anywheresoftware.b4a.objects.collections.Map();
    public static String _settingsfilename = "settings.properties";

    public static String  _getsetting2(anywheresoftware.b4a.BA _ba,String _key,String _defaultvalue) throws Exception{
        if (_settings.IsInitialized()==anywheresoftware.b4a.keywords.Common.False) {
            if (anywheresoftware.b4a.keywords.Common.File.Exists(_getfolder(_ba),_settingsfilename)) {
                _settings = anywheresoftware.b4a.keywords.Common.File.ReadMap(_getfolder(_ba),_settingsfilename);
             }else {
                if (true) return _defaultvalue;
             };
         };
        if (true) return BA.ObjectToString(_settings.GetDefault((Object)(_key.toLowerCase()),(Object)(_defaultvalue)));
        return "";
    }

    public static String  _getfolder(anywheresoftware.b4a.BA _ba) throws Exception{
        String _targetdir = "";
        _targetdir = anywheresoftware.b4a.keywords.Common.File.getDirInternal();
        if (anywheresoftware.b4a.keywords.Common.File.getExternalWritable()) {
            _targetdir = anywheresoftware.b4a.keywords.Common.File.getDirDefaultExternal();};
        if (true) return _targetdir;
        return "";
    }

    public void _onCreate() {
        _settings = new anywheresoftware.b4a.objects.collections.Map();
        BA activityBA;
        activityBA = new BA(this, layout, processBA, "amonet.mobile2", "amonet.mobile2.main");
        try{
            main._currentthemeid = (int)(Double.parseDouble(_getsetting2(activityBA,"CurrentThemeId","0")));
        } catch(Exception e){
            BA.LogInfo("Error" + e);
        }

        if (main._currentthemeid != 0)
            setTheme(main._currentthemeid);
       
    }
    #end if
     
    Last edited: Oct 14, 2015
    Multiverse app likes this.
  15. Erel

    Erel Administrator Staff Member Licensed User

    Can you upload a project with this code?
     
  16. joneden

    joneden Active Member Licensed User

    Hi Erel,
    I can send you the full source - is there somewhere that I can send it directly to you?
    Regards
    Jon
     
  17. Erel

    Erel Administrator Staff Member Licensed User

    If you can please create a small example with only the theme related code.
     
  18. joneden

    joneden Active Member Licensed User

    OK sample attached. I've just cut out as much as possible. Start the app and press login. Theme should switch to green and it does but the status bar stays blue.
    With a second activity the status bar on that does show as green BUT always remains blue on the initial activity.

    Essentially the status bar only ever is set on the main activity as the theme specified in the manifest file. Hopefully it's something obvious.
     

    Attached Files:

    Multiverse app likes this.
  19. Erel

    Erel Administrator Staff Member Licensed User

    The problem is with the interaction with the custom action bar. As you can see in the above video the native action bar does change the color correctly.
     
  20. joneden

    joneden Active Member Licensed User

    Hi Erel,

    No the action bar is fine - it's the status bar at the top of the screen that is the problem as seen in the attached. Once logged in the status bar changes to a deeper green as it should be on this page...
     

    Attached Files:

    Multiverse app likes this.
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice