4

I'm targeting API level 14+, so I've used Activity.recreate() for theme switching in my app. It worked out nice, except a black screen will flash for about 0.5s.

I used to think it is impossible to provide a better experience here, until I saw a material designed app which successfully switched its theme with a crossfade. But unluckily I failed to recall its name since I uninstalled it from my phone some time ago.

I've tried Activity.overridePendingTransition(), it did not work, and I believe the reason is that the recreate() call is much like a configuration change so the mechanism is different from finishing and launching a brand new activity.


(And while trying to find that app I came across another magic theme switching app, even without calling recreate(). Hum... Anybody know how the trick is done?)

Theme switching on the fly GIF

Who said themes were immutable? Changing the primary and accent colors on…


EDIT:

I found that the GIF above is kind of a distraction from the original question, so I turned it into a link.

My original question is that, is there any method to change (switch) theme with an appropriate transition?

Changing all the things on screen by Brute force is not switching the app's theme; it just appear to be though, but it can lead to many problems.

Sad to find out the above GIF may only be a hacky brute force attack, but still thanks to @Emanuel Moecklin for pointing this out.

But I still hope a "(truly) switching theme with transition" solution can come up, or someone tell me that Activity.recreate() cannot be animated and no other ways can switch themes better.

Hai Zhang
  • 5,574
  • 1
  • 44
  • 51

2 Answers2

5

After all these years I've learned an easy way.

Instead of Activity.recreate(), use the follwing code fragment:

finish();
startActivity(new Intent(this, getClass()));
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);

And it will give you a nice animation between themes.

Bonus: You can manually save & restore instance state to preserve UI state, and ignore user input during restarting by overriding input related methods (dispatch*Event()) on Activity.

Hai Zhang
  • 5,574
  • 1
  • 44
  • 51
0

Check out this answer to a similar question: https://stackoverflow.com/a/26511725/534471

What the app you mention in your question does, isn't changing the theme but changing the color of the status bar, the action bar and the navigation bar:

Status Bar:

getWindow().setStatusBarColor(colorStatus);

Action Bar:

ActionBar actionBar = getSupportActionBar();
actionBar.setBackgroundDrawable( new ColorDrawable( colorAction ) );

Navigation Bar:

getWindow().setNavigationBarColor(colorStatus);

My guess is that the accent color is changed by just setting the background color of the two visible elements (the floating action button and the tab navigation). Tab navigation colors can be changed like this:

ActionBar actionBar = getSupportActionBar();
actionBar.setStackedBackgroundDrawable( new ColorDrawable( accentColor ) );   
Community
  • 1
  • 1
Emanuel Moecklin
  • 28,488
  • 11
  • 69
  • 85
  • But not only that, you can observe that the splitter and arrows of `ListView`s inside other tabs also changed its accent color. Is the trick really so hacky that it simply manually changes all the things inside all the tabs? – Hai Zhang Mar 04 '15 at 06:24
  • And thank your for your answer, I've also updated (and clarified) my question a bit. – Hai Zhang Mar 04 '15 at 06:39
  • Cool. Changing the question after you got an answer. Good luck finding someone to waste their time on this. – Emanuel Moecklin Mar 04 '15 at 16:32