【问题标题】:Using setTheme() at runtime only changes text color在运行时使用 setTheme() 只会改变文本颜色
【发布时间】:2019-03-21 12:34:14
【问题描述】:

我正在尝试为我的应用实现一个深色主题。用户可以在选项菜单中轻松地在正常和黑暗之间切换——效果很好。但是在运行时更改主题时,只有文字颜色会发生变化,我不知道为什么。

styles.xml 中我的深色主题:

<style name="Dark" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/dark_background</item>
    <item name="colorPrimaryDark">@color/dark_top</item>
    <item name="colorAccent">@color/dark_button</item>
    <item name="colorButtonNormal">@color/dark_button</item>
    <item name="android:colorBackground">@color/dark_background</item>
    <item name="android:itemBackground">@color/dark_background</item>
    <item name="android:textColor">@color/white</item>
    <item name="android:textColorHint">#EAEAEA</item>
    <item name="android:textColorPrimary">@color/white</item>
    <item name="android:textColorSecondary">@color/white</item>
    <item name="android:textColorTertiary">@color/white</item>
</style>

我的风格设置方式:

setTheme(R.style.Dark);

更换主题前: before

更换主题后: after

我真的不知道为什么。是因为NavigationView吗?

【问题讨论】:

  • 你在哪里使用 setTheme(R.style.Dark)?
  • 当前在 setContentView 之后,否则应用程序崩溃
  • 您应该在 setContentView() 之前调用它,这就是您的视图不会改变颜色的原因。请在 setContentView() 之前调用它时发送您的崩溃日志。

标签: java android styles themes textcolor


【解决方案1】:

确保您在调用setTheme() 之前调用setContentView() 或膨胀视图。根据documentation,您必须在上下文中实例化任何视图之前使用setTheme()。使用 recreate() 创建一个新的 Activity 实例,以便您可以在 onCreate() 方法中应用更改后的主题。

如果您稍微搜索一下,您可以找到几个主题切换的示例。这是一个此类示例的链接: https://gist.github.com/alphamu/f2469c28e17b24114fe5

我使用PreferenceManager 来存储此类设置,以便在我有多个活动需要使用该设置时轻松访问。除非您已经有更好的方法来存储用户的主题选择,否则我建议您使用以下示例。

MyAppPreferences 类示例:

public class MyAppPreferences {

    private static SharedPreferences getPrefs(Context context) {
        return PreferenceManager.getDefaultSharedPreferences(context);
    }

    public static int getThemeId(Context context, int defaultThemeId) {
        return getPrefs(context).getInt("CurrentThemeId", defaultThemeId);
    }
    public static void setThemeId(Context context, int value) {
        getPrefs(context).edit().putInt("CurrentThemeId", value).commit();
    }

}

使用 MyAppPreferences 类的示例 Activity 类:

public class MyActivity extends AppCompatActivity implements OnClickListener {

    private Button btnDark;
    private Button btnLight;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);            
        // Set the theme
        // If there is nothing set, the light theme will be used by default
        setTheme(MyAppPreferences.getThemeId(this, R.style.Light));
        setContentView(R.layout.myLayout);

        btnDark = (Button) this.findViewById(R.id.viewbtnDark);
        btnDark.setOnClickListener(this);

        btnLight = (Button) this.findViewById(R.id.viewbtnLight);
        btnLight.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        // 1. Set the theme preference
        // 2. Recreate the activity to "apply" the theme
        if (v.equals(btnDark)) {
            MyAppPreferences.setThemeId(this, R.style.Dark);
            this.recreate();
        } else if (v.equals(btnLight)) {
            MyAppPreferences.setThemeId(this, R.style.Light);
            this.recreate();
        }
    }

}

您的示例主题不显示 windowActionBar 或 windowNoTitle 设置,因此如果您碰巧使用默认主题并且您没有在深色主题中以相同的方式设置这些选项,您仍然可能会遇到崩溃。检查 Logcat 是否有类似这样的错误:java.lang.IllegalStateException: This Activity already has an action bar supplied by the window decor.

深色主题示例

<style name="Dark" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/dark_background</item>
    <item name="colorPrimaryDark">@color/dark_top</item>
    <item name="colorAccent">@color/dark_button</item>
    <item name="colorButtonNormal">@color/dark_button</item>
    <item name="android:colorBackground">@color/dark_background</item>
    <item name="android:itemBackground">@color/dark_background</item>
    <item name="android:textColor">@color/white</item>
    <item name="android:textColorHint">#EAEAEA</item>
    <item name="android:textColorPrimary">@color/white</item>
    <item name="android:textColorSecondary">@color/white</item>
    <item name="android:textColorTertiary">@color/white</item>
</style>

【讨论】:

  • 如果在 super.onCreate 之前设置它,我的应用程序在启动时崩溃。 @Override protected void onCreate(Bundle savedInstanceState) { setTheme(R.style.Dark); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar);
  • 确保在super.onCreate() 之后、setContentView() 之前调用setTheme()。现在在调试模式下运行您的应用程序并检查您的 Logcat 选项卡。你看到这样的错误吗? java.lang.IllegalStateException: This Activity already has an action bar supplied by the window decor. 如果你这样做了,我注意到你的示例主题没有关闭窗口操作栏和标题。如果您使用默认模板,这些选项可能会在默认主题中设置,在这种情况下,您还需要在深色主题中设置它们。我会更新我的答案来提及这一点。
  • 没有在主题中设置“windowActionBar”和“windowNoTitle”是问题所在。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-15
  • 2021-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-16
相关资源
最近更新 更多