Как изменить текущую тему во время выполнения в Android

Я создал функцию PreferenceActivity, которая позволяет пользователю выбирать тему, которую он хочет применить ко всему приложению.

Когда пользователь выбирает тему, этот код выполняется:

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

Но, хотя я проверил с отладчиком, что код выполняется, я не вижу никаких изменений в пользовательском интерфейсе.

Темы определяются в 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 в любой специальной точке кода? Мое приложение состоит из нескольких видов деятельности, если это помогает.

Solutions Collecting From Web of "Как изменить текущую тему во время выполнения в Android"

Я также хотел бы увидеть этот метод, где вы устанавливаете один раз для всех своих действий. Но насколько я знаю, вы должны установить в каждом мероприятии, прежде чем показывать какие-либо мнения.

Для справки проверьте это:

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() , чтобы избежать бесконечного цикла.

У меня такая же проблема, но я нашел решение.

 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 recreate() (как упоминалось TPReal ) только перезапустит текущую активность, но предыдущие действия будут по-прежнему находиться в фоновом стеке, и тема не будет применяться к ним.

Итак, еще одно решение этой проблемы – полностью воссоздать стек задач, например:

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

РЕДАКТИРОВАТЬ:

Просто поставьте код выше после того, как вы измените тему в пользовательском интерфейсе или в другом месте. Все ваши действия должны иметь метод setTheme() onCreate() до onCreate() , возможно, в некоторых родительских действиях. Это также обычный подход для хранения темы, выбранной в SharedPreferences , ее чтения, а затем установки с использованием 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 } 

Этот код предназначен для воссоздания спада активности и изменения темы. Вы должны написать свой собственный 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(); 

Я знаю, что я опаздываю, но я бы хотел опубликовать решение здесь: здесь проверьте полный исходный код. Это код, который я использовал при смене темы с использованием настроек.

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

Это то, что я создал для Material Design. Пусть это поможет вам.

Посмотрите MultipleThemeMaterialDesign

Этот способ работает для меня:

  @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 и воссоздать его таким образом, что ваша деятельность будет создана снова, и все представления будут созданы с новой темой.

Вместо

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

Где-то (например, при нажатии кнопки):

 YourActivity.this.recreate(); 

Вы должны воссоздать деятельность, иначе – изменений не произойдет

Вызовите SetContentView (Resource.Layout.Main) после setTheme ().

Это не повлияло на меня:

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