如何在Android运行时更改当前主题

我创build了一个PreferenceActivity,允许用户select他想要应用到整个应用程序的主题。

当用户select一个主题时,这个代码被执行:

if (...) { getApplication().setTheme(R.style.BlackTheme); } else { getApplication().setTheme(R.style.LightTheme); } 

但是,即使我已经与debugging器检查了代码正在执行,但我看不到用户界面中的任何更改。

主题在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> 

任何想法可能会发生什么,以及如何解决它? 我应该在代码中的任何特殊点调用setTheme吗? 如果有帮助,我的应用程序由几个活动组成。

我也希望看到这个方法,你为所有的活动设置一次。 但据我所知,在展示任何观点之前,你必须在每个活动中进行设定。

参考检查这个:

http://www.anddev.org/applying_a_theme_to_your_application-t817.html

编辑(从该论坛复制):

 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); } 

如果您想更改已经存在的活动的主题,请在setTheme()之后调用recreate() setTheme()

注意:如果在onCreate()更改主题,则不要调用重新创build,以避免无限循环。

我得到了同样的问题,但我find了解决办法。

 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); } } 

recreate() (如TPReal提到的)只会重新启动当前的活动,但以前的活动仍然会回到栈中,主题不会被应用到它们。

所以,这个问题的另一个解决scheme是完全重新创build任务堆栈,如下所示:

  TaskStackBuilder.create(getActivity()) .addNextIntent(new Intent(getActivity(), MainActivity.class)) .addNextIntent(getActivity().getIntent()) .startActivities(); 

编辑:

在UI或其他位置执行主题更改后,只需将上面的代码放在上面。 你所有的活动都应该有方法setTheme() onCreate()之前调用,可能在一些父活动。 在SharedPreferencesselect主题,读取并使用setTheme()方法进行设置也是一种setTheme()方法。

我们必须在调用“super.onCreate()”“setContentView()”方法之前设置主题。

查看此链接 ,以便在运行时将新主题应用于整个应用程序。

我有一个类似的问题,我用这种方式解决..

 @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 } 

这段代码是为了重新创buildActivity的Bundle并改变主题。 你必须编写你自己的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(); 

这是我为材料devise创造的。 愿它能帮助你。

看看MultipleThemeMaterialDesign

我知道我迟到了,但是我想在这里发布一个解决scheme:在这里查看完整的源代码。 这是使用偏好更改主题时使用的代码。

 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); } 

代替

 getApplication().setTheme(R.style.BlackTheme); 

使用

 setTheme(R.style.BlackTheme); 

我的代码:在onCreate()方法中:

 super.onCreate(savedInstanceState); if(someExpression) { setTheme(R.style.OneTheme); } else { setTheme(R.style.AnotherTheme); } setContentView(R.layout.activity_some_layout); 

某处(例如,点击button):

 YourActivity.this.recreate(); 

您必须重新创build活动,否则 – 更改不会发生

这样对我有用:

  @Override protected void onCreate(Bundle savedInstanceState) { setTheme(GApplication.getInstance().getTheme()); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } 

那么你想改变一个新的主题:

 GApplication.getInstance().setTheme(R.style.LightTheme); recreate(); 

你可以完成Acivity,然后重新创build,这样你的活动将被重新创build,所有的视图将被创build与新的主题。

在setTheme()之后调用SetContentView(Resource.Layout.Main)。

这对我没有影响:

 public void changeTheme(int newTheme) { setTheme(newTheme); recreate(); } 

但是这工作:

 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(); }