如何在代码中为整个应用程序设置主题,但不在Manifest中?

Jud*_*udy 8 android themes

我知道如何在清单中将主题设置为整个应用程序,但如何以编程方式将主题设置为整个应用程序?我正在尝试这个:getApplicationContext.setTheme(R.style.mytheme),但它不起作用.

我认为getApplicationContext应用程序的上下文,可以设置整个应用程序的主题.

小智 11

我花了很多时间让它工作,现在我的应用程序有可选择的Light和Dark主题,甚至可以动态选择立即进入游戏,包括Prefs.下面是我使用的资源以及我在某些starge玩过的其他一些想法.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--The base theme ensures nothing is shown until the first activity. All activities and fragmenst must-->
    <!--set a them in onCreate or in AndroidManifext or they wil crash because of no title.-->
    <!--Using Theme.Holo.NoActionBar suppresses the ActionBar initially so Icon doesn't show until new theme is set.-->
    <style name="MyAppThemeInitial" parent="@android:style/Theme.Holo">
        <!--<item name="android:windowBackground">@color/initial_background_grey</item>-->
        <!--<item name="android:actionBarStyle">@style/MyActionBar</item>-->
        <item name="android:windowDisablePreview">true</item>

    </style>
    <style name="MyAppThemeDark" parent="@android:style/Theme.Holo">
        <item name="android:windowBackground">@color/black</item>
    </style>
    <style name="MyAppThemeLight" parent="android:Theme.Holo.Light">
    <item name="android:windowBackground">@color/white</item>
    </style>


<!--&lt;!&ndash;This is so that only the icon is showing in the intial theme&ndash;&gt;-->
    <!--&lt;!&ndash; ActionBar styles &ndash;&gt;-->
    <!--<style name="MyActionBar" parent="@android:style/Widget.Holo.ActionBar">-->
        <!--<item name="android:background">@android:color/transparent</item>-->
        <!--<item name="android:titleTextStyle">@style/MyActionBarTextAppearance</item>-->
    <!--</style>-->

    <!--<style name="MyActionBarTextAppearance">-->
        <!--<item name="android:textColor">@android:color/transparent</item>-->
    <!--</style>-->

</resources> 
Run Code Online (Sandbox Code Playgroud)

这里的关键项目是

<item name="android:windowDisablePreview">true</item>
Run Code Online (Sandbox Code Playgroud)

我花了一段时间才意识到这一点.我的应用程序在启动时做了一些繁重的工作,因此在我设置onCreate之前没有强制性Manifest主题显示非常重要.

为了能够动态地重新启动应用程序,我检查这是否是应用程序的启动/重启方式.

SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
boolean useThemeLight = sp.getBoolean("useThemeLight", false);
//Since this Activity can also be started by the Theme Toggle in the Action bar we need to see if
//there is a TOGGLE_THEME extra which only it uses
Intent curIntent = this.getIntent();
if (curIntent.getExtras() != null && curIntent.getExtras().containsKey(TOGGLE_THEME)) {
    if(curIntent.getStringExtra(TOGGLE_THEME).equals("Dark")){
        this.setTheme(R.style.MyAppThemeDark);
        CurrentTheme = "Dark";
    }else{
        this.setTheme(R.style.MyAppThemeLight);
        CurrentTheme = "Light";
    }
    activityThemeToggleActive = true;
} else {
    if (useThemeLight) {
        this.setTheme(R.style.MyAppThemeLight);
        CurrentTheme = "Light";
    } else {
        this.setTheme(R.style.MyAppThemeDark);
        CurrentTheme = "Dark";
    }
}
Run Code Online (Sandbox Code Playgroud)

在偏好中,我这样做.

SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
boolean useThemeLight = sp.getBoolean("useThemeLight", false);
if (useThemeLight) {
    this.setTheme(R.style.MyAppThemeLight);
} else {
    this.setTheme(R.style.MyAppThemeDark);
}
Run Code Online (Sandbox Code Playgroud)

希望这能让你开始.问候,约翰.


100*_*abh 6

setThemesuper.onCreate()类似下面的代码之前调用

  public void onCreate(Bundle icicle) {
           if(Utility.isThemed)
             setTheme(R.style.Mytheme);
           super.onCreate(icicle);
    .....
    .....
}
Run Code Online (Sandbox Code Playgroud)

  • @Judy:在某些情况下, super.onCreate() 可能会实例化某些视图,因此在 super.onCreate() 之前调用 setTheme() 是一个好主意。 (2认同)

raj*_*ath 5

setTheme 中,文档说:

请注意,这应该在上下文中实例化任何视图之前调用(例如在调用 setContentView(View) 或 inflate(int, ViewGroup) 之前)。

你照顾过那个吗?


Jos*_*arl 3

您不能将其从 Java 应用于整个应用程序,除非您使用 Java 代码修改清单文件。您想要应用主题的其他活动可能甚至没有运行,那么 Android 如何向它们应用主题呢?退出并返回程序后,所有更改都将丢失,您需要再次应用主题。

getApplicationContext确实返回应用程序上下文 - 但仅仅因为一个方法采用 aContext并不意味着传递它 anApplicationContext会突然使其影响整个应用程序。事实上,一般来说它不会,并且会像使用普通上下文一样工作。

相反,不同上下文的重要性在于它们存在的时间不同 - 活动上下文是随活动一起创建和销毁的,但应用程序上下文是在第一个应用程序组件运行时创建的,并在最后一个组件被销毁时销毁的。

  • 不确定是否可以——但是您必须以 XML 形式读取该文件,对其进行修改,然后将其保存回来。如果您想为所有活动动态设置主题,那么我认为最好的想法是创建一个模板活动,在 onCreate 中设置其主题,然后让所有其他活动扩展此类。 (5认同)