1

When toggling Dark Mode in iOS, we can see the app previews in the app switcher immediately change their appearances even though suspended in the background.

This post aims to find out if it's possible to achieve this in React Native (regardless of using bare React Native or Expo), and if not, is there anyway we can help make it possible?

Observe the animation:
animation
Or click here if it's not displaying.

  1. The native Settings app, even though suspended in background, changes it's appearance when Dark Mode is toggled
  2. The Expo client app, also suspended in the background (the app switcher was opened from Home, not while Expo is in use) does not change its appearance when Dark Mode is toggled. It will only do so when I tap to go back into the app
  3. I'm not sure if Expo client is built with React Native because the behavior described in "2." does not always happen. But I've tried creating my own RN app with react-native-appearance and the colors do not change when suspended (as portrayed in the animation)


At the moment, there is a hacky way to partially achieve this, but I don't think anybody could stand to ship their app with it.

<View style={{
    backgroundColor: isDarkModeOn ? 'black' : 'white', // remove this
}} />

Don't specify backgroundColor at all and it will behave like a native app even when suspended and viewed from the app switcher, probably because it's using a native value by default… but:

  • that only applies to backgroundColor
  • and only if it's a <View/> (or something equivalent)
  • and is limited to black and white

We still need to rely on JavaScript as long as one of the conditions above are not met.


I would like to believe that there's a solution out there that I'm not aware of. But so far none of the dark mode tutorials I find mention about this concern.

GlyphCat
  • 144
  • 1
  • 3
  • 15
  • Your link to animation leads to a private gif! We cannot watch it! – Fotios Tsakiris Mar 13 '20 at 08:41
  • @FotisTsakiris The link is just an extra in case the embedded one is not displaying, I've set it to public by the way. – GlyphCat Mar 13 '20 at 08:46
  • GR8! I wish I could help. Why don't you sent an email to William Candilon wcandillon@gmail.com. He is known also for his YouTube series "Can it be done in React Native". I'm sure he can help! – Fotios Tsakiris Mar 13 '20 at 14:01

1 Answers1

0

This can definitely be done, with code like this:

import { DynamicColorIOS } from 'react-native';
export const C = {
  normalText:   DynamicColorIOS({ dark: '#999', light: '#222'}),
  normalTextBold: DynamicColorIOS({ dark: '#ccc', light: '#000'}),
  titleText:    DynamicColorIOS({ dark: '#777', light: '#999'}),
  headingText:  DynamicColorIOS({ dark: '#999', light: '#666'}),
  borderLine:   DynamicColorIOS({ dark: '#888', light: '#888'}),
  background:   DynamicColorIOS({ dark: '#000', light: '#fff'}),
  internalLink: DynamicColorIOS({ dark: '#1EAEDB', light: '#01a'}),
};

I have no idea how this impacts Android compatibility, but if you change all of your stylesheets to use these paired-up colors (C.background on the right-hand side of a style property), you get proper light mode and dark mode color changing and animating by the system, as you describe. You can even test this in the iOS simulator with Cmd+Shift+A to change the appearance, which will animate from light to dark mode and back if you press it a second time.

Jared Updike
  • 7,165
  • 8
  • 46
  • 72