How to Check Whether Dark Mode Is Enabled in iOS/Ipados

How can I check whether dark mode is enabled in iOS/iPadOS?

SwiftUI

With the \.colorScheme key of an Environment variable:

struct ContentView: View {
@Environment(\.colorScheme) var colorScheme

var body: some View {
Text(colorScheme == .dark ? "In dark mode" : "In light mode")
}
}

Also, it automatically updates on the change of the environment color scheme.



UIKit

To check the current, all object those conform to UITraitEnvironment protocol, including all UIView subclasses and all UIViewConttroller subclasses have access to the current style:

myUIView.traitCollection.userInterfaceStyle == .dark
myUIViewController.traitCollection.userInterfaceStyle == .dark

To detect live changes of the style, here is the full detailed answer

How to check for Dark Mode in iOS?

UIKit has had UITraitCollection for a while now. Since iOS 9 you could use UITraitCollection to see whether the device supports 3D Touch (a sad conversation for another day)

In iOS 12, UITraitCollection got a new property: var userInterfaceStyle: UIUserInterfaceStyle which supports three cases: light, dark, and unspecified

Since UIViewController inherits UITraitEnvironment, you have access to the ViewController's traitCollection. This stores userInterfaceStyle.

UITraitEnviroment also has some nifty protocol stubs that help your code interpret when state changes happen (so when a user switches from the Dark side to the Light side or visa versa). Here's a nice coding example for you:

class MyViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()

if self.traitCollection.userInterfaceStyle == .dark {
// User Interface is Dark
} else {
// User Interface is Light
}

}

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
// Trait collection has already changed
}

override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
// Trait collection will change. Use this one so you know what the state is changing to.
}
}

Detect if iOS13 Dark Mode is enabled from Flutter/Dart

Here's how you can set different colors for light and dark mode, the app will automatically switch if the phone is set to dark mode or light mode.

MaterialApp(
theme: ThemeData(
brightness: Brightness.light,
primaryColor: Colors.red,
),
darkTheme: ThemeData(
brightness: Brightness.dark,
// additional settings go here
),
);

::Update::

You can also get the platform brightness (Brightness.light / Brightness.dark) using

WidgetsBinding.instance.window.platformBrightness

but you will have to use the WidgetsBindingObserver mixin and override the method below

@override
void didChangePlatformBrightness() {
print(WidgetsBinding.instance.window.platformBrightness); // should print Brightness.light / Brightness.dark when you switch
super.didChangePlatformBrightness(); // make sure you call this
}

see https://api.flutter.dev/flutter/widgets/WidgetsBindingObserver-class.html on how to use the mixin.

How to detect Light\Dark mode change in iOS 13?

SwiftUI

With a simple environment variable on the \.colorScheme key:

struct ContentView: View {
@Environment(\.colorScheme) var colorScheme

var body: some View {
Text(colorScheme == .dark ? "Its Dark" : "Its. not dark! (Light)")
}
}


UIKit

As it described in WWDC 2019 - Session 214 around 23:30.

As I expected, this function is getting called a lot including when colors changing. Along side with many other functions for ViewController and presentationController. But there is some especial function designed for that has a similar signature in all View representers.

Take a look at this image from that session:

WWDC 2019 - Session 214

Gray: Calling but not good for my issue, Green: Designed for this

So I should call it and check it inside this function:

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)

if traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) {
dropShadowIfNeeded()
}
}

This will guarantee to be called just once per change.

if you are only looking for the initial state of the style, check out this answer here

Swift How can you reset the colors of all the subviews on a page?

You need to use dynamic colors in order to have them adapt automatically. Here

UITraitCollection.current.userInterfaceStyle == .light ? .black : .white

you check for the interface style right at that moment and set the color, but that code is not re-evaluated automatically when the trait environment changes.

Instead, you can use one of the system colors (like .background or .label), which will adapt to dark/light mode changes automatically. If you want to define your own, the easiest way would be using asset catalogs. When you add a color there, you can define how it looks in light and dark mode separately.

Why doesn't my iOS app disable dark mode?

Simply you can add a new key UIUserInterfaceStyle in your app info.plist (Notes: Xcode 12 and above has renamed to Appearance) and set its value to Light or Dark. this will override the app default style to the value you provide.

so you don't need to bother about having it anywhere else

How to set dark mode for NSToolbar in macOS Catalyst app?

This can be done by adding an macOS plugin which has access to the whole AppKit API. Instructions can be found here:
How to Access the AppKit API from Mac Catalyst Apps

Then you can set the desired appearance there at runtime, for example:

NSApplication.shared.appearance = NSAppearance(named: .darkAqua)

How to support dark mode for a UIlabelTextColor in iOS 13.x?

You can define a Color Sets in your asset catalog with different variants for light and dark mode:

Color Asset

You can then use the color in Interface Builder or code with UIColor(named: "Color").
It will also adapt to appearance changes automatically.



Related Topics



Leave a reply



Submit