3

So here is the situation:

  1. I have DogActivity and FavoritesActivity. DogActivity is just a ListView. When you click on a Dog in the list, it takes you to FavoritesActivity.
  2. I want to have a number of themes ready to go. They don’t need to be dynamically generated. They can already exist in XML form.
  3. Depending on which dog the user selects from the list, I want to have the FavoritesActivity shown in one of my pre-existing themes.

I hear talks about ContextWrapper, but I am not sure how to apply it. Any thoughts on how I may accomplish this?

Details:

Here is the usual single theme:

for 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>

for 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>

Want I want to do:

Essentially I just want to change the colorPrimary, colorPrimaryDark and colorAccent on the fly and have all the styles and themes and XML layouts that use them to change. So if I can change those colors before I launch FavoritesActivity then that would solve my problems.

Lii
  • 11,553
  • 8
  • 64
  • 88
Nouvel Travay
  • 6,292
  • 13
  • 40
  • 65
  • To the people who replied, I am not absent. I am here. And I am implementing your suggestions. I am running into some problems for where say colorPrimary or colorAccent is used directly in `layout.xml` files. They are not changing along. For now only the primary colors are changing and by that I mean colorPrimary and colorPrimaryDark. So far it's looking like unless I can change the values of these colors directly, then I am out of luck. In the mean time, +1 to all. – Nouvel Travay Sep 06 '16 at 20:45

3 Answers3

2

You can just send the dog type as an Intent extra, and then use the setTheme() method to set the appropriate Theme.

For this example, suppose you just have two Themes:

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

Then, in DogActivity, set an Intent Extra to the Dog type the user selected from the ListView:

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

Then, in FavoritesActivity, load the correct Theme:

@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);
    //.....
 }
Daniel Nugent
  • 43,104
  • 15
  • 109
  • 137
  • I am using your implementation. You've seen my theme for `v21`. Is there a way to set the colors for `android.support.design.widget.TabLayout` in that theme? What I mean is `tabIndicatorColor` and `tabSelectedTextColor`. – Nouvel Travay Sep 06 '16 at 21:14
  • Ahh, the TabLayout complicates it a bit. To start, take a look at my other answer here: http://stackoverflow.com/a/32613364/4409409 I'm not sure how you could change that on the fly though.... – Daniel Nugent Sep 06 '16 at 21:42
  • This is probably the best answer I am going to get. So thanks! – Nouvel Travay Sep 06 '16 at 23:16
1

I've accomplish it quite simply on my latest project, you just have to set the values on the theme via Java. Like the following code:

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
}

that's very useful because you can very easily replace just a few values and keep the rest as the original, or change everything from the original. It all depends what argument you pass to the applyTheme method.

Also is great you don't have to mock with ContextThemeWrapper. The values are there on the theme and that's it.

https://developer.android.com/reference/android/content/res/Resources.Theme.html#applyStyle(int, boolean)

Budius
  • 39,391
  • 16
  • 102
  • 144
0

You can use this.recreate() method for this.

Based on https://stackoverflow.com/a/29722976/7547681 answer.

Arslan Tazhibaev
  • 262
  • 1
  • 4
  • 10