À partir d'iOS / iPadOS 13, un style d'interface utilisateur sombre est disponible, similaire au mode sombre introduit dans macOS Mojave. Comment puis-je vérifier si l'utilisateur a activé le mode sombre à l'échelle du système?
16 Réponses :
Vous devriez vérifier la variable userInterfaceStyle
de UITraitCollection
, comme sur tvOS et macOS.
switch traitCollection.userInterfaceStyle { case .light: //light mode case .dark: //dark mode case .unspecified: //the user interface style is not specified }
Vous devez utiliser la fonction traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?)
UIView
/ UIViewController
pour détecter les changements dans l'environnement de l'interface (y compris les changements dans le style de l'interface utilisateur).
Depuis la documentation Apple Developer :
Le système appelle cette méthode lorsque l'environnement de l'interface iOS change. Implémentez cette méthode dans les contrôleurs de vue et les vues, en fonction des besoins de votre application, pour répondre à de tels changements. Par exemple, vous pouvez ajuster la disposition des sous-vues d'un contrôleur de vue lorsqu'un iPhone est pivoté de l'orientation portrait à l'orientation paysage. L'implémentation par défaut de cette méthode est vide.
Les éléments d'interface utilisateur par défaut du système (tels que UITabBar
ou UISearchBar
) s'adaptent automatiquement au nouveau style d'interface utilisateur.
En plus de traitCollectionDidChange(_:)
, vous pouvez également vérifier le changement de UIView
est layoutSubviews()
, draw(_:)
, updateConstraints()
, ou tintColorDidChange()
, ou dans UIViewController
's updateViewConstraints()
, viewWillLayoutSubviews()
ou viewDidLayoutSubviews()
. Toutes ces méthodes sont appelées à chaque fois que le style de l'interface utilisateur change.
Cela vous donnera le style d'interface utilisateur de la vue actuelle. Si vous l'avez remplacé pour cette vue particulière, il ne vous indiquera pas le style du système.
Comme mentionné par daveextreme, la vérification du style d'interface utilisateur de la vue actuelle ne renvoie pas toujours le style système lorsque vous utilisez la propriété overrideUserInterfaceStyle
. Dans de tels cas, il peut être préférable d'utiliser le code suivant:
switch UIScreen.main.traitCollection.userInterfaceStyle { case .light: //light mode case .dark: //dark mode case .unspecified: //the user interface style is not specified }
Le meilleur point pour détecter les changements est la fonction traitCollectionDidChange (_ previousTraitCollection: UITraitCollection?) De UIView / UIViewController.
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) let hasUserInterfaceStyleChanged = previousTraitCollection.hasDifferentColorAppearance(comparedTo: traitCollection) // Bool // Update your user interface based on the appearance }
La détection des changements d'apparence est simple en remplaçant traitCollectionDidChange sur les contrôleurs de vue. Ensuite, accédez simplement au traitCollection.userInterfaceStyle du contrôleur de vue.
Cependant, il est important de se rappeler que traitCollectionDidChange peut être appelé pour d'autres changements de trait, tels que la rotation de l'appareil. Vous pouvez vérifier si l'apparence actuelle est différente en utilisant cette nouvelle méthode:
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) let userInterfaceStyle = traitCollection.userInterfaceStyle // Either .unspecified, .light, or .dark // Update your user interface based on the appearance }
dans objective-c vous voudriez faire:
if( self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark ){ //is dark }else{ //is light }
Vous pouvez utiliser cette extension:
import UIKit extension UIApplication { @available(iOS 13.0, *) var userInterfaceStyle: UIUserInterfaceStyle? { return self.keyWindow?.traitCollection.userInterfaceStyle } } @available(iOS 13.0, *) func setSystemTheme() { switch UIApplication.shared.userInterfaceStyle { case .dark?: currentTheme = .dark case .light?: currentTheme = .light default: break } }
Pour iOS 13 , vous pouvez utiliser cette propriété pour vérifier si le style actuel est en mode sombre ou non:
if #available(iOS 13.0, *) { if UITraitCollection.current.userInterfaceStyle == .dark { print("Dark mode") } else { print("Light mode") } }
Ceci est très bien si vous voulez vérifier dans AppDelegate, car il ne dispose pas d' une traitCollection
variables comme UIViewController
Merci! Enfin une bonne réponse au problème AppDelegate :)
Cela ne réagit pas en mode sombre désactivé. Si vous utilisez window?.overrideUserInterfaceStyle = .light
UITraitCollection.current.userInterfaceStyle
peut renvoyer .dark
.
1 / pour UIView / UIViewController:
//Never use this! You will get wrong value in app extensions (ex. ToDay widget) UIScreen.main.traitCollection.userInterfaceStyle == .dark //WRONG!
2 / pour statique ou autre:
UITraitCollection.current.userInterfaceStyle == .dark
MAIS:
self.traitCollection.userInterfaceStyle == .dark
En fait, le dernier (UIScreen ...) était le seul moyen d'obtenir le paramètre de mode sombre de l'utilisateur dans les paramètres de l'appareil après avoir remplacé le userInterfaceStyle dans mon application. De cette façon, j'ai pu implémenter un bouton "Suivre le mode sombre iOS" qui met immédiatement à jour le thème de couleur de l'application même si j'ai des thèmes personnalisés et une sélection à côté de cela. Malheureusement, il est impossible de gérer de manière fiable la couleur du texte de la barre d'état individuellement sans remplacer userInterfaceStyle.
Notez que cela peut aider quelqu'un: si UIUserInterfaceStyle
défini sur light
dans votre info.plist
, ces méthodes info.plist
toujours light
@LeonidSilver Merci beaucoup !!! Supprimez l'élément UIUserInterfaceStyle dans info.plist pour le thème système (.unspecified) en utilisant!
Objectif c
Pour détecter lorsque le mode sombre est activé ou désactivé via le centre de contrôle, utilisez une notification «appDidBecomeActive» qui sera déclenchée lorsque vous reviendrez sur votre application.
//---------------------------------------------------------------------------- // appDidBecomeActive //---------------------------------------------------------------------------- -(void)appDidBecomeActive:(NSNotification*)note { if (@available(iOS 13.0, *)) { if( self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark ){ //dark mode } else { //not dark mode } } else { //fall back for older versions } }
N'oubliez pas de le supprimer lorsque vous avez terminé:
//------------------------------------------------------------------------------------ // viewWillDisappear //------------------------------------------------------------------------------------ - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; }
Faites ce dont vous avez besoin lorsque le mode sombre change:
//---------------------------------------------------------------------------- // viewWillAppear //---------------------------------------------------------------------------- - (void)viewWillAppear { [super viewWillAppear]; [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(appDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil]; }
Créez une fonction de classe pour la méthode d'écriture 1 fois et utilisez-la partout où vous le souhaitez
func isDarkMode() -> Bool{ if #available(iOS 12.0, *) { if UIScreen.main.traitCollection.userInterfaceStyle == .dark { return true } else { return false } } else { return false } }
Pour Swift:
if (@available(iOS 12.0, *)) { switch (UIScreen.mainScreen.traitCollection.userInterfaceStyle) { case UIUserInterfaceStyleDark: // put your dark mode code here break; case UIUserInterfaceStyleLight: case UIUserInterfaceStyleUnspecified: break; default: break; } }
Pour l'objectif C:
if #available(iOS 12.0, *) { switch UIScreen.main.traitCollection.userInterfaceStyle { case .dark: // put your dark mode code here case .light: case .unspecified: } }
Pour plus d'informations, regardez cette vidéo WWDC2019
J'ai fini par l'utiliser pour Xamarin.Forms dans mon projet iOS. De loin la meilleure réponse là-bas. (Bonne réponse solide informée fonctionnant mieux que la 100e copie par un blogueur du doku officiel de MS pour Xamarin.) @Pedro Trujillo vous avez sauvé ma journée. Merci!
Une belle extension peut-être?
public extension UIViewController { @available(iOS 12.0, *) public var isDarkMode: Bool { traitCollection.userInterfaceStyle == .dark } }
Méthode d'assistance ci-dessous qui fonctionne sur n'importe quelle version iOS:
view.backgroundColor = isDarkMode ? .black : .white
Usage:
var isDarkMode: Bool { guard #available(iOS 12.0, *) else { return false } return UIScreen.main.traitCollection.userInterfaceStyle == .dark }
Bienvenue dans Stack Overflow. Les vidages de code sans aucune explication sont rarement utiles. Stack Overflow consiste à apprendre, pas à fournir des extraits à copier et à coller aveuglément. Veuillez modifier votre question et expliquer en quoi elle fonctionne mieux que ce que le PO a fourni.
@Chris. Merci pour le commentaire mais littéralement chaque réponse ici est un vidage de code ... La question est très simple et la réponse aussi. Merci de l'avoir signalé, je vais ajouter plus d'explications
Cela ne rend pas les réponses de code uniquement acceptables. Ce commentaire a été signalé soit comme une "réponse de faible qualité", probablement parce que c'était purement du code, soit comme une "réponse tardive" (je ne me souviens plus laquelle) et j'ai commenté via la file d'attente d'examen. Il est toujours préférable de souligner ce que vous avez changé, pourquoi vous l'avez changé et comment votre réponse s'améliore par rapport à celles existantes. Je compte dix réponses antérieures à la vôtre. Faites ressortir le vôtre.
Vous pouvez facilement détecter le mode sombre ou le mode clair avec cette méthode Swift 5
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { if traitCollection.userInterfaceStyle == .light { print("Light mode") } else { print("Dark mode") }}
Avec la clé \.colorScheme
d'une variable d' Environment
:
myUIView.traitCollection.userInterfaceStyle == .dark myUIViewController.traitCollection.userInterfaceStyle == .dark
En outre, il se met automatiquement à jour lors du changement de la palette de couleurs de l'environnement.
Pour vérifier le courant, tous les objets conformes au protocole UITraitEnvironment
, y compris toutes les sous-classes UIView
et toutes les sous-classes UIViewConttroller
ont accès au style actuel:
struct ContentView: View { @Environment(\.colorScheme) var colorScheme var body: some View { Text(colorScheme == .dark ? "In dark mode" : "In light mode") } }
Pour détecter les changements de style en direct, voici la réponse détaillée complète
J'ai utilisé cette méthode dans mon ContentView pour changer la couleur d'accentuation d'une interface de barre d'onglets. À la fin de la vue par onglets, j'ai utilisé .accentColor (colorScheme == .dark? .Green: .black)
Vous pouvez utiliser le code suivant pour vérifier le mode clair ou sombre dans votre projet:
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) let userInterfaceStyle = traitCollection.userInterfaceStyle // Either .unspecified, .light, or .dark // Update your user interface based on the appearance }
Vous pouvez également vérifier les changements dans le style d'interface:
func viewDidLoad() { super.viewDidLoad() switch traitCollection.userInterfaceStyle { case .light, .unspecified: // light mode detected case .dark: // dark mode detected } }
Tout comme dans macOS depuis Mojave, vous pouvez définir des images pour les modes clair et sombre dans votre catalogue d'actifs afin que ces images soient utilisées automatiquement:
isDarkMode ? .black : .white
Cette interface utilisateur est en fait disponible depuis tvOS 10 et iOS 12 - sur iOS 12, elle était uniquement disponible en "inverser les couleurs" dans les options d'accessibilité
Le commentaire d'Aaron Brager est quelque peu inexact - oui, vous pouvez "inverser les couleurs" mais c'est très différent d'activer le mode sombre. Cela peut donner une fausse impression que votre application est toujours utilisable. Par exemple: si vous mélangez par inadvertance des couleurs système avec les vôtres, alors inverser les inverse toutes. Cependant, en mode sombre, les couleurs du système changeront mais pas les vôtres. Ainsi, comme Touchgram v1.1.0, vous pouvez vous retrouver avec du texte presque blanc sur un fond bleu très pâle. L'examen de l'App Store ne prend PAS cela!
Voici pour vérifier l'état actuel et c'est pour observer les changements en direct de l'état . Les deux réponses couvrent UIKit / AppKit / SwiftUI et etc.