以编程方式更改活动的主题


121

在某些情况下,我需要从活动中删除对话框主题,但是它似乎不起作用。这是一个例子

第一次活动:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    startActivity(new Intent(MainActivity.this, SecondActivity.class));
}

第二项活动:

public void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setTheme(android.R.style.Theme);
    setContentView(R.layout.activity_second);
}

清单摘录:

 <activity android:name="SecondActivity" android:theme="@android:style/Theme.Dialog"></activity>

当我运行它时,仍然以对话框为主题。

API10

谢谢。

Answers:


183

文档所述,您必须setTheme在任何视图输出之前调用。似乎super.onCreate()参与了view处理。

所以,动态主题,你只需要调用之间切换setTheme之前super.onCreate是这样的:

public void onCreate(Bundle savedInstanceState) {
    setTheme(android.R.style.Theme);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_second);
}

适用于具有Android 5.1堆栈的MotoG(v1)。如果对您不起作用,请共享设备+安卓版本。
lenrok258 '16

我必须定义一个主题,如下所述: stackoverflow.com/a/44236460/3211335然后按照此答案的描述进行设置。效果很好。
LaloLoop

无论如何,我们只能设置一次主题...而不是每页设置主题
gayan1991'1

我使用共享首选项保存主题,但是在重新启动应用程序时,先出现第一个主题,然后显示第二个主题!
Mohammad Afrashteh

1
@ gayan1991您可以使用其他活动来定义您的主题,并使所有其他活动对此进行扩展:pastebin.com/r93qrRDG编辑:使用pastebin具有更好的格式
SocialSupaCrew

46

user1462299的响应效果很好,但如果包含片段,它们将使用原始活动主题。要将主题也应用于所有片段,您可以改用 Context 的getTheme()方法:

@Override
public Resources.Theme getTheme() {
    Resources.Theme theme = super.getTheme();
    if(useAlternativeTheme){
        theme.applyStyle(R.style.AlternativeTheme, true);
    }
    // you could also use a switch if you have many themes that could apply
    return theme;
}

您不再需要在onCreate()方法中调用setTheme()。您将以这种方式覆盖在此上下文中获取当前主题的每个请求。


2
// @无奈的人:关心解释你不喜欢我的回应吗?
比约恩·凯歇尔(BjörnKechel)2016年

应该在Activity或各个Fragment中重写getTheme()吗?我已经在Activity中实现了这一点,但是Fragments仍在使用原始的Activity主题。
saltandpepper

@saltandpepper在活动中覆盖它就足够了。确保您的片段代码和布局不会再次更改。
比约恩·凯歇尔(BjörnKechel)

这对我来说不起作用,但是stackoverflow.com/a/15496425/494179中提供的答案可以。
saltandpepper

2
不错的用户user1269737,所以您应该确保没有繁重的计算。在简单情况下返回一个样式不会影响性能。
比约恩Kechel

12

我知道我迟到了,但我想在这里发表一个解决方案:
检查完整的源代码在这里
这是我使用首选项更改主题时使用的代码。

SharedPreferences pref = PreferenceManager
        .getDefaultSharedPreferences(this);
String themeName = pref.getString("prefSyncFrequency3", "Theme1");
if (themeName.equals("Africa")) {
    setTheme(R.style.AppTheme);



} else if (themeName.equals("Colorful Beach")) {
    //Toast.makeText(this, "set theme", Toast.LENGTH_SHORT).show();
    setTheme(R.style.beach);


} else if (themeName.equals("Abstract")) {
    //Toast.makeText(this, "set theme", Toast.LENGTH_SHORT).show();

    setTheme(R.style.abstract2);

} else if (themeName.equals("Default")) {

    setTheme(R.style.defaulttheme);

}

请注意,您必须将代码放在setcontentview之前。

祝您编码愉快!


为什么?答案是corect ?!
dondondon

我使用共享首选项保存主题,但是在重新启动应用程序时,先出现第一个主题,然后显示第二个主题!
Mohammad Afrashteh

0

这对我来说很好用:

theme.applyStyle(R.style.AppTheme, true)

用法:

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    //The call goes right after super.onCreate() and before setContentView()
    theme.applyStyle(R.style.AppTheme, true)
    setContentView(layoutId)
    onViewCreated(savedInstanceState)
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.