This question already has an answer here:
这个问题已经有了答案:
- Implementing user choice of theme 3 answers
- 实现用户对主题3答案的选择
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吗?如果有帮助的话,我的应用程序包含几个活动。
13 个解决方案
#1
70
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);
}
#2
43
If you want to change theme of an already existing activity, call recreate()
after setTheme()
.
如果您想更改已存在活动的主题,请在setTheme()之后调用restart()。
Note: don't call recreate if you change theme in onCreate()
, to avoid infinite loop.
注意:如果在onCreate()中更改了主题,不要调用re,以避免无限循环。
#3
17
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.
重新创建()(正如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或其他地方执行主题更改之后,只需将代码放在上面。您的所有活动应该在onCreate()之前调用方法setTheme(),可能在某些父活动中。它也是一个普通的方法来存储在SharedPreferences中选择的主题,读取它,然后使用setTheme()方法进行设置。
#4
15
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);
}
}
#5
9
We have to set theme before calling 'super.onCreate()' and 'setContentView()' method.
我们必须在调用“super.onCreate()”和“setContentView()”方法之前设置主题。
Check out this link for applying new theme to whole application at runtime.
请查看此链接,以便在运行时将新主题应用到整个应用程序。
#6
8
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中,您可以使用方法rebuild ()
Bundle temp_bundle = new Bundle();
onSaveInstanceState(temp_bundle);
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("bundle", temp_bundle);
startActivity(intent);
finish();
#7
2
This is what i have created for Material Design. May it will helpful you.
这是我为材料设计创造的。但愿这对你有帮助。
Have a look for MultipleThemeMaterialDesign
你是否想要一款多功能的设计?
#8
2
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..
我知道我迟到了,但我想在这里发布一个解决方案:在这里检查完整的源代码。这是我在使用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);
}
#9
2
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
你必须重新创造活动,否则不会发生改变。
#10
2
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();
#11
1
You can finish the Acivity and recreate it afterwards in this way your activity will be created again and all the views will be created with the new theme.
您可以完成Acivity,然后以这种方式重新创建您的活动,并且所有的视图都将使用新的主题创建。
#12
0
Call SetContentView(Resource.Layout.Main) after setTheme().
调用SetContentView(Resource.Layout.Main)setTheme()。
#13
0
This had no effect for me:
这对我没有影响:
public void changeTheme(int newTheme) {
setTheme(newTheme);
recreate();
}
But this worked:
但这工作:
int theme = R.style.default;
protected void onCreate(Bundle savedInstanceState) {
setTheme(this.theme);
super.onCreate(savedInstanceState);
}
public void changeTheme(int newTheme) {
this.theme = newTheme;
recreate();
}
#1
70
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);
}
#2
43
If you want to change theme of an already existing activity, call recreate()
after setTheme()
.
如果您想更改已存在活动的主题,请在setTheme()之后调用restart()。
Note: don't call recreate if you change theme in onCreate()
, to avoid infinite loop.
注意:如果在onCreate()中更改了主题,不要调用re,以避免无限循环。
#3
17
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.
重新创建()(正如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或其他地方执行主题更改之后,只需将代码放在上面。您的所有活动应该在onCreate()之前调用方法setTheme(),可能在某些父活动中。它也是一个普通的方法来存储在SharedPreferences中选择的主题,读取它,然后使用setTheme()方法进行设置。
#4
15
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);
}
}
#5
9
We have to set theme before calling 'super.onCreate()' and 'setContentView()' method.
我们必须在调用“super.onCreate()”和“setContentView()”方法之前设置主题。
Check out this link for applying new theme to whole application at runtime.
请查看此链接,以便在运行时将新主题应用到整个应用程序。
#6
8
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中,您可以使用方法rebuild ()
Bundle temp_bundle = new Bundle();
onSaveInstanceState(temp_bundle);
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("bundle", temp_bundle);
startActivity(intent);
finish();
#7
2
This is what i have created for Material Design. May it will helpful you.
这是我为材料设计创造的。但愿这对你有帮助。
Have a look for MultipleThemeMaterialDesign
你是否想要一款多功能的设计?
#8
2
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..
我知道我迟到了,但我想在这里发布一个解决方案:在这里检查完整的源代码。这是我在使用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);
}
#9
2
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
你必须重新创造活动,否则不会发生改变。
#10
2
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();
#11
1
You can finish the Acivity and recreate it afterwards in this way your activity will be created again and all the views will be created with the new theme.
您可以完成Acivity,然后以这种方式重新创建您的活动,并且所有的视图都将使用新的主题创建。
#12
0
Call SetContentView(Resource.Layout.Main) after setTheme().
调用SetContentView(Resource.Layout.Main)setTheme()。
#13
0
This had no effect for me:
这对我没有影响:
public void changeTheme(int newTheme) {
setTheme(newTheme);
recreate();
}
But this worked:
但这工作:
int theme = R.style.default;
protected void onCreate(Bundle savedInstanceState) {
setTheme(this.theme);
super.onCreate(savedInstanceState);
}
public void changeTheme(int newTheme) {
this.theme = newTheme;
recreate();
}