Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

setTheme works but only after loading theme from manifest

I'm trying to set the theme of my Activity during runtime, choosing one of a number of themes. I want the chosen theme to display immediately on startup of the Activity.

In the <application> part of my manifest I have set a default theme with android:theme="@style/AppTheme". And then in my onCreate() I use setTheme(R.style.DarkAppTheme) to set the theme to a user-selected theme (replacing DarkAppTheme with the selected theme).

And based on research it seems that setTheme() should go before onCreate() and before setContentView(), which I do.

BUT although this works to display the Activity in the user selected theme, the Activity first loads with what looks like the default theme, and then after a short delay the correct theme loads.

If I set the user selected theme directly in the manifest, that loads immediately as I want, but of course that is hardcoded and I want to change this dynamically based on a shared preference.

How do I avoid the visible changeover? I want the user selected theme to be displayed right from the start.

Thanks.

like image 670
drmrbrewer Avatar asked May 19 '15 16:05

drmrbrewer


People also ask

How to set app theme in Android studio programmatically?

In Android Studio, open themes. xml (app > res > values > themes > themes. xml). Notice the theme name, Theme.


1 Answers

The Activity first loads with what looks like the default theme, and then after a short delay the correct theme loads... How do I avoid the visible changeover?

There are 2 parts to an Activity 'Enter/Opening' window animation, when your app is first launched from the icon on the Home Screen:

Video screenshot of Android 7 Activity open window animation

  1. The 'dark gray rectangle appear' animation. This is the initial blank screen that the system process draws when launching the app (source). It's also known as the "theme preview" screen or "splash screen". It can be white if your app uses a Light theme.
  2. The 'fade in (or circular reveal) of the view layout'. This is the animation of your view layout appearing on top of the dark gray rectangle. It happens after part 1.

Part 1 is what you identified as "what looks like the default theme". You can disable this first part with the following item in your Activity/App style:

<item name="android:windowDisablePreview">true</item>

This will prevent the 'dark gray rectangle appear' animation, and only allow the 'reveal of the view layout', to therefore avoid the visible changeover or flicker. But there are caveats:

  1. You have to ensure that your Activity launches quickly, because there will be no visual animation feedback for the user until your layout is fully loaded. That's why the theme preview is normally on by default.
  2. It causes strange bugs on context menus: For any PopupWindow, the 'Enter' animation will no longer happen, and it will just display instantly ('Exit' animations are not affected). This also applies to system PopupWindows like the overflow menu list, and the drop-down list of an AutoCompleteTextView. This bug happens on Android 4/5/6, but not on Android 7/8. More info here.

Documentation of windowDisablePreview:

Flag allowing you to disable the splash screen for a window. The default value is false; if set to true, the system can never use the window's theme to show a splash screen preview before your actual instance is shown to the user.

Further info:

  • How to set a theme to whole application in code, but not in the Manifest?
  • Android - Disable dummy starting window of application
like image 190
Mr-IDE Avatar answered Sep 23 '22 15:09

Mr-IDE