Итак, вот ситуация:

  1. У меня есть DogActivity и FavoritesActivity. DogActivity - это просто ListView. Когда вы нажимаете на Dog в списке, вы переходите к FavoritesActivity.
  2. Я хочу иметь несколько готовых тем. Их не нужно создавать динамически. Они уже могут существовать в форме XML.
  3. В зависимости от того, какую собаку пользователь выбирает из списка, я хочу, чтобы FavoritesActivity отображался в одной из моих ранее существовавших тем.

Я слышал разговоры о ContextWrapper, но не знаю, как это применить. Есть мысли о том, как я могу это сделать?

Подробности:

Вот обычная одиночная тема:

для v21 / styles.xml

<resources>
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:colorControlHighlight">@color/colorAccentLight</item>
        <item name="android:colorControlNormal">@color/colorAccent</item>
        <item name="android:itemTextAppearance">@style/AppTheme.itemTextStyle</item>
        <item name="popupMenuStyle">@style/PopupMenu.MyAppTheme</item>
    </style>

    <style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
        <item name="android:windowDrawsSystemBarBackgrounds">true</item>
        <item name="android:statusBarColor">@android:color/transparent</item>
        <item name="android:colorControlHighlight">@color/colorAccentLight</item>
    </style>

    <style name="AppTheme.itemTextStyle" parent="@android:style/TextAppearance.Widget.IconMenu.Item">
        <item name="android:textColor">@color/colorPrimary</item>
    </style>
</resources>

для styles.xml

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
</style>

Хочу, я хочу делать:

По сути, я просто хочу изменить colorPrimary, colorPrimaryDark и colorAccent на лету и иметь все стили, темы и макеты XML, которые используют их для изменения. Так что, если я смогу изменить эти цвета перед запуском FavoritesActivity, это решит мои проблемы.

3
Nouvel Travay 6 Сен 2016 в 22:38

3 ответа

Лучший ответ

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

В этом примере предположим, что у вас всего две темы:

<style name="AppThemeOne" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
</style>

<style name="AppThemeTwo" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">@color/colorPrimaryCustom</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDarkCustom</item>
    <item name="colorAccent">@color/colorAccentCustom</item>
</style>

Затем в DogActivity установите Intent Extra для типа Dog, который пользователь выбрал из ListView:

Intent intent = new Intent(DogActivity.this, FavoritesActivity.class);
intent.putExtra("dog_type", "terrier");
startActivity(intent);

Затем в FavoritesActivity загрузите правильную тему:

@Override
protected void onCreate(Bundle savedInstanceState) {

    String dogType = getIntent().getStringExtra("dog_type");
    if (dogType.equals("terrier")) {
        setTheme(R.style.AppThemeOne);
    } else {
        setTheme(R.style.AppThemeTwo);
    }
    super.onCreate(savedInstanceState);
    setContentView(R.layout.favorites_layout);
    //.....
 }
2
Daniel Nugent 6 Сен 2016 в 20:02

В моем последнем проекте я сделал это довольно просто, вам просто нужно установить значения в теме через Java. Как следующий код:

public class FavoritesActivity extends AppCompatActivity { // it can be Activity too

@Override
public void onCreate(Bundle savedInstanceState) {
   if( ... check condition to change theme ) {
      // this will replace every value from FavoritesActivity theme by the
      // the values on `other_style` theme. 
      getTheme().applyStyle(R.style.other_style, true);
   }
   // call super AFTER applying the theme
   super.onCreate(savedInstanceState);

   .. carry on your normal stuff
}

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

Также здорово, что вам не нужно издеваться над ContextThemeWrapper. Ценности есть по теме и все.

https://developer.android.com/reference /android/content/res/Resources.Theme.html#applyStyle(int, логическое)

1
Budius 6 Сен 2016 в 19:54

Вы можете использовать для этого метод this.recreate().

На основании ответа https://stackoverflow.com/a/29722976/7547681.

0
Arslan Tazhibaev 28 Мар 2019 в 22:09