Как изменить текущую тему во время выполнения на 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
в любой специальной точке кода? Мое приложение состоит из нескольких действий, если это помогает.
Ответы
Ответ 1
Я хотел бы также увидеть этот метод, где вы устанавливаете один раз для всех своих действий. Но насколько я знаю, вы должны установить в каждом мероприятии, прежде чем показывать какие-либо мнения.
Для справки проверьте это:
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);
}
Ответ 2
Если вы хотите изменить тему уже существующего действия, вызовите recreate()
после setTheme()
.
Примечание: не вызывайте воссоздание, если вы меняете тему в onCreate()
, чтобы избежать бесконечного цикла.
Ответ 3
recreate()
(как упоминалось TPReal) перезапустит текущую активность, но предыдущие действия будут по-прежнему находиться в обратном стеке, и тема не будет применяться к ним.
Итак, еще одно решение этой проблемы - полностью воссоздать стек задач, например:
TaskStackBuilder.create(getActivity())
.addNextIntent(new Intent(getActivity(), MainActivity.class))
.addNextIntent(getActivity().getIntent())
.startActivities();
EDIT:
Просто поместите код выше после того, как вы измените тему в пользовательском интерфейсе или в другом месте. Все ваши действия должны иметь метод setTheme()
, называемый до onCreate()
, возможно, в некоторых родительских действиях. Это также обычный подход для сохранения темы, выбранной в SharedPreferences
, прочитайте ее, а затем установите с помощью метода setTheme()
.
Ответ 4
У меня такая же проблема, но я нашел решение.
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
Мы должны задать тему перед вызовом метода 'super.onCreate()' и 'setContentView().
Ознакомьтесь с этой ссылкой для применения новой темы для всего приложения во время выполнения.
Ответ 6
У меня была аналогичная проблема, и я решил таким образом.
@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();
Ответ 7
Это то, что я создал для Material Design. Пусть это поможет вам.
Посмотрите MultipleThemeMaterialDesign
Ответ 8
Я знаю, что я опаздываю, но я бы хотел опубликовать решение здесь:
Проверьте полный исходный код здесь.
Это код, который я использовал при изменении темы, используя настройки.
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
Вместо
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();
Вам нужно воссоздать активность, иначе - изменения не произойдет
Ответ 10
Этот способ работает для меня:
@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();
Ответ 11
Вы можете закончить Acivity и воссоздать его таким образом, что ваша деятельность будет создана снова, и все представления будут созданы с новой темой.
Ответ 12
Вызов SetContentView (Resource.Layout.Main) после setTheme().
Ответ 13
Это не повлияло на меня:
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();
}