如何在 Android 运行时更改当前主题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2482848/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to change current Theme at runtime in Android
提问by Guido
I've created a PreferenceActivity that allows the user to choose the theme he wants to apply to the entire application.
我创建了一个 PreferenceActivity,它允许用户选择他想要应用于整个应用程序的主题。
When the user selects a theme, this code is executed:
当用户选择一个主题时,会执行以下代码:
if (...) {
getApplication().setTheme(R.style.BlackTheme);
} else {
getApplication().setTheme(R.style.LightTheme);
}
But, even though I've checked with the debugger that the code is being executed, I can't see any change in the user interface.
但是,即使我已经用调试器检查过代码正在执行,我也看不到用户界面的任何变化。
Themes are defined in res/values/styles.xml
, and Eclipse does not show any error.
主题在 中定义res/values/styles.xml
,Eclipse 不显示任何错误。
<resources>
<style name="LightTheme" parent="@android:style/Theme.Light">
</style>
<style name="BlackTheme" parent="@android:style/Theme.Black">
</style>
</resources>
Any idea about what could be happening and how to fix it?
Should I call setTheme
at any special point in the code? My application consists of several Activities if that helps.
关于可能发生什么以及如何解决它的任何想法?我应该setTheme
在代码中的任何特殊点调用吗?如果有帮助,我的应用程序包含几个活动。
采纳答案by Pentium10
I would like to see the method too, where you set once for all your activities. But as far I know you have to set in each activity before showing any views.
我也想看看这个方法,你为你的所有活动设置一次。但据我所知,在显示任何视图之前,您必须在每个活动中进行设置。
For reference check this:
作为参考检查这个:
http://www.anddev.org/applying_a_theme_to_your_application-t817.html
http://www.anddev.org/applying_a_theme_to_your_application-t817.html
Edit (copied from that forum):
编辑(从该论坛复制):
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Call setTheme before creation of any(!) View.
setTheme(android.R.style.Theme_Dark);
// ...
setContentView(R.layout.main);
}
Edit
If you call setTheme
after super.onCreate(savedInstanceState);
your activity recreated but if you call setTheme
before super.onCreate(savedInstanceState);
your theme will set and activity
does not recreate anymore
编辑
如果您setTheme
在super.onCreate(savedInstanceState);
重新创建活动后调用但如果您setTheme
在super.onCreate(savedInstanceState);
主题设置之前调用并且活动不再重新创建
protected void onCreate(Bundle savedInstanceState) {
setTheme(android.R.style.Theme_Dark);
super.onCreate(savedInstanceState);
// ...
setContentView(R.layout.main);
}
回答by TPReal
If you want to change theme of an already existing activity, call recreate()
after setTheme()
.
如果要更改现有活动的主题,请recreate()
在 之后调用setTheme()
。
Note: don't call recreate if you change theme in onCreate()
, to avoid infinite loop.
注意:如果您在 中更改主题,请不要调用重新创建onCreate()
,以避免无限循环。
回答by Yuriy Yunikov
recreate()
(as mentioned by TPReal) will only restart current activity, but the previous activities will still be in back stack and theme will not be applied to them.
recreate()
(如TPReal 所述)只会重新启动当前活动,但之前的活动仍将在后堆栈中,并且不会对它们应用主题。
So, another solution for this problem is to recreate the task stack completely, like this:
因此,此问题的另一个解决方案是完全重新创建任务堆栈,如下所示:
TaskStackBuilder.create(getActivity())
.addNextIntent(new Intent(getActivity(), MainActivity.class))
.addNextIntent(getActivity().getIntent())
.startActivities();
EDIT:
编辑:
Just put the code above after you perform changing of theme on the UI or somewhere else. All your activities should have method setTheme()
called before onCreate()
, probably in some parent activity. It is also a normal approach to store the theme chosen in SharedPreferences
, read it and then set using setTheme()
method.
在 UI 或其他地方执行主题更改后,只需将上面的代码放在上面。你所有的活动都应该有方法setTheme()
调用 before onCreate()
,可能在一些父活动中。将所选主题存储在 中SharedPreferences
,阅读它然后使用setTheme()
方法进行设置也是一种正常的方法。
回答by Monty
i got the same problem but i found the solution.
我遇到了同样的问题,但我找到了解决方案。
public class EditTextSmartPhoneActivity extends Activity implements DialogInterface.OnClickListener
{
public final static int CREATE_DIALOG = -1;
public final static int THEME_HOLO_LIGHT = 0;
public final static int THEME_BLACK = 1;
int position;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
position = getIntent().getIntExtra("position", -1);
switch(position)
{
case CREATE_DIALOG:
createDialog();
break;
case THEME_HOLO_LIGHT:
setTheme(android.R.style.Theme_Holo_Light);
break;
case THEME_BLACK:
setTheme(android.R.style.Theme_Black);
break;
default:
}
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
private void createDialog()
{
/** Options for user to select*/
String choose[] = {"Theme_Holo_Light","Theme_Black"};
AlertDialog.Builder b = new AlertDialog.Builder(this);
/** Setting a title for the window */
b.setTitle("Choose your Application Theme");
/** Setting items to the alert dialog */
b.setSingleChoiceItems(choose, 0, null);
/** Setting a positive button and its listener */
b.setPositiveButton("OK",this);
/** Setting a positive button and its listener */
b.setNegativeButton("Cancel", null);
/** Creating the alert dialog window using the builder class */
AlertDialog d = b.create();
/** show dialog*/
d.show();
}
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
AlertDialog alert = (AlertDialog)dialog;
int position = alert.getListView().getCheckedItemPosition();
finish();
Intent intent = new Intent(this, EditTextSmartPhoneActivity.class);
intent.putExtra("position", position);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
回答by Francesco Ditrani
I had a similar problem and I solved in this way..
我有一个类似的问题,我以这种方式解决了..
@Override
public void onCreate(Bundle savedInstanceState) {
if (getIntent().hasExtra("bundle") && savedInstanceState==null){
savedInstanceState = getIntent().getExtras().getBundle("bundle");
}
//add code for theme
switch(theme)
{
case LIGHT:
setTheme(R.style.LightTheme);
break;
case BLACK:
setTheme(R.style.BlackTheme);
break;
default:
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//code
}
this code is for recreate the Activity saving Bundle and changing the theme. You have to write your own onSaveInstanceState(Bundle outState); From API-11 you can use the method recreate() instead
此代码用于重新创建活动保存包并更改主题。您必须编写自己的 onSaveInstanceState(Bundle outState); 从 API-11 开始,您可以使用方法 recreate() 代替
Bundle temp_bundle = new Bundle();
onSaveInstanceState(temp_bundle);
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("bundle", temp_bundle);
startActivity(intent);
finish();
回答by Lalit Sharma
回答by Vitaly Zinchenko
Instead of
代替
getApplication().setTheme(R.style.BlackTheme);
use
用
setTheme(R.style.BlackTheme);
My code: in onCreate() method:
我的代码:在 onCreate() 方法中:
super.onCreate(savedInstanceState);
if(someExpression) {
setTheme(R.style.OneTheme);
} else {
setTheme(R.style.AnotherTheme);
}
setContentView(R.layout.activity_some_layout);
Somewhere (for example, on a button click):
某处(例如,单击按钮时):
YourActivity.this.recreate();
You have to recreate activity, otherwise - change won't happen
您必须重新创建活动,否则 - 更改不会发生
回答by duongnx
This way work for me:
这种方式对我有用:
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(GApplication.getInstance().getTheme());
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
Then you want to change a new theme:
然后你想改变一个新的主题:
GApplication.getInstance().setTheme(R.style.LightTheme);
recreate();
回答by Pratik Butani
This is what i have created for Material Design. May it will helpful you.
这是我为 Material Design 创建的。愿它对你有帮助。
Have a look for MultipleThemeMaterialDesign
回答by dondondon
I know that i am late but i would like to post a solution here: Check the full source code here. This is the code i used when changing theme using preferences..
我知道我迟到了,但我想在这里发表一个解决方案:检查完整的源代码在这里。这是我使用首选项更改主题时使用的代码..
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);
}