Программно изменить тему Activity

121

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

Первое действие:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    startActivity(new Intent(MainActivity.this, SecondActivity.class));
}

Второе действие:

public void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setTheme(android.R.style.Theme);
    setContentView(R.layout.activity_second);
}

Отрывок из манифеста:

 <activity android:name="SecondActivity" android:theme="@android:style/Theme.Dialog"></activity>

Когда я запускаю, он все еще тематический диалог.

API10

Спасибо.

user1462299
источник

Ответы:

184

Как говорится в документации , вы должны вызывать setThemeперед выходом любого представления. Похоже, что super.onCreate()принимает участие в viewобработке.

Итак, чтобы переключаться между темами динамически, вам просто нужно позвонить setThemeперед super.onCreateэтим следующим образом:

public void onCreate(Bundle savedInstanceState) {
    setTheme(android.R.style.Theme);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_second);
}
user1462299
источник
У меня работает на MotoG (v1) со стеком Android 5.1. Если это не работает для вас, поделитесь версией устройства + Android.
lenrok258
Мне пришлось определить тему, как описано здесь: stackoverflow.com/a/44236460/3211335 А затем установить ее, как описано в этом ответе. Отлично работает.
LaloLoop
В любом случае, мы могли бы установить тему только один раз ... вместо того, чтобы задавать тему для каждой страницы?
gayan1991
Я использую общие настройки для сохранения темы, но при перезапуске приложения на мгновение появляется первая тема, а затем отображается вторая тема!
Mohammad Afrashteh
1
@ gayan1991 Вы можете использовать другое действие, чтобы определить свою тему и сделать все остальные ваши действия расширенными, например: pastebin.com/r93qrRDG edit: используйте pastebin для лучшего форматирования
SocialSupaCrew
46

Ответ user1462299 работает отлично, но если вы включите фрагменты , они будут использовать исходную тему действий. Чтобы применить тему ко всем фрагментам, вы можете вместо этого переопределить метод getTheme () контекста:

@Override
public Resources.Theme getTheme() {
    Resources.Theme theme = super.getTheme();
    if(useAlternativeTheme){
        theme.applyStyle(R.style.AlternativeTheme, true);
    }
    // you could also use a switch if you have many themes that could apply
    return theme;
}

Вам больше не нужно вызывать setTheme () в методе onCreate (). Таким образом вы переопределяете каждый запрос, чтобы получить текущую тему в этом контексте.

Бьорн Кечел
источник
2
@ кто проголосовал против: объясните, что вам не нравится в моем ответе?
Björn Kechel
Следует ли переопределить getTheme () в действии или в соответствующих фрагментах? Я реализовал это в Activity, но фрагменты все еще используют исходную тему Activity.
saltandpepper 07
@saltandpepper Достаточно переопределить его в Activity. Убедитесь, что код фрагмента и макет не меняют его снова.
Björn Kechel 08
У меня это не сработало, но ответ, представленный в stackoverflow.com/a/15496425/494179, сработал .
saltandpepper 09
2
Хороший момент user1269737, так что вы должны убедиться, что нет тяжелых вычислений. Простое возвращение стиля в простом случае условия не повлияет на производительность.
Björn Kechel
12

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

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

}

Обратите внимание, что вы должны поместить код перед setcontentview ..

С КОДИРОВКОЙ!

dondondon
источник
Зачем? ответ - корект ?!
dondondon
Я использую общие настройки для сохранения темы, но при перезапуске приложения на мгновение появляется первая тема, а затем отображается вторая тема!
Mohammad Afrashteh
0

Это отлично работает для меня:

theme.applyStyle(R.style.AppTheme, true)

Использование:

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    //The call goes right after super.onCreate() and before setContentView()
    theme.applyStyle(R.style.AppTheme, true)
    setContentView(layoutId)
    onViewCreated(savedInstanceState)
}
Тамим Аттафи
источник