49
votes

Comment puis-je vérifier si le mode sombre est activé dans iOS / iPadOS?

À 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?


3 commentaires

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.


16 Réponses :


41
votes

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.


2 commentaires

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.



20
votes

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
}


0 commentaires

1
votes

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
}


0 commentaires

15
votes

dans objective-c vous voudriez faire:

if( self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark ){

        //is dark
}else{

    //is light

}


0 commentaires

1
votes

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
        }
    }


0 commentaires

35
votes

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")
    }
}


3 commentaires

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 .



13
votes

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


3 commentaires

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!



7
votes

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];

}


0 commentaires

5
votes

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
    }
}  


0 commentaires

8
votes

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


1 commentaires

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!



0
votes

Une belle extension peut-être?

public extension UIViewController {
    @available(iOS 12.0, *)
    public var isDarkMode: Bool { traitCollection.userInterfaceStyle == .dark }
}


0 commentaires

2
votes

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
}


3 commentaires

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.



0
votes

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")
}}


0 commentaires

3
votes

SwiftUI

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.


UIKit

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


1 commentaires

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)



0
votes

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:


0 commentaires

0
votes
isDarkMode ? .black : .white

0 commentaires