Bonjour à tous!Je m'appelle Andrey, je fais partie de l'équipe My Broker. Je vais vous dire que vous avez ajouté la prise en charge d'un thème sombre dans iOS.Apple dans iOS 13 a ajouté un thème sombre pour l'ensemble du système, les utilisateurs peuvent choisir une apparence claire ou sombre dans les paramètres iOS. En mode sombre, le système utilise une palette de couleurs plus foncées pour tous les écrans, vues, menus et commandes.
Peu importe - passez sous le chat.Prise en charge de la conception sombre
L'application créée par défaut dans Xcode 11 prend en charge la conception sombre dans iOS 13. Mais pour la mise en œuvre complète du mode sombre, vous devez apporter des modifications supplémentaires:- Les couleurs doivent prendre en charge le design clair et foncé
- Les images doivent prendre en charge la conception claire et sombre
Apple a ajouté plusieurs couleurs de système qui prennent en charge le design clair et sombre. Dans iOS 13, le nouvel initialiseur UIColor a été introduit :init (dynamicProvider: @escaping (UITraitCollection) -> UIColor)
Ajoutez une fonction statique pour créer des couleurs avec prise en charge de la commutation entre le design clair et sombre:extension UIColor {
static func color(light: UIColor, dark: UIColor) -> UIColor {
if #available(iOS 13, *) {
return UIColor.init { traitCollection in
return traitCollection.userInterfaceStyle == .dark ? dark : light
}
} else {
return light
}
}
}
CGColor ne prend pas en charge la commutation automatique entre la lumière et l'obscurité. Vous devez modifier manuellement le CGColor après avoir modifié la conception.override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
layer.borderColor = UIColor.Pallete.black.cgColor
}
Il est également possible d'ajouter de la couleur pour la décoration sombre dans les ressources.
Mais je préfère ajouter des couleurs dans le code.UIColor.Palleteextension UIColor {
struct Pallete {
static let white = UIColor.color(light: .white, dark: .black)
static let black = UIColor.color(light: .black, dark: .white)
static let background = UIColor.color(light: .white, dark: .hex("1b1b1d"))
static let secondaryBackground = UIColor(named: "secondaryBackground") ?? .black
static let gray = UIColor.color(light: .lightGray, dark: .hex("8e8e92"))
}
}
Pour les images, ajoutez simplement une variante de l'image pour un design sombre directement dans les ressources.
Faisons une petite application pour un exemple.
L'application contiendra deux fenêtres et trois écrans.Première fenêtre: écran d'autorisation.Deuxième fenêtre: écran ruban et écran de profil utilisateur.Captures d'écran au design clair et sombre Changer de thèmes clairs et sombres
Créez une énumération pour le sujet:
enum Theme: Int, CaseIterable {
case light = 0
case dark
}
Nous ajoutons la possibilité de stocker le thème actuel afin de le restaurer après le redémarrage de l'application.extension Theme {
@Persist(key: "app_theme", defaultValue: Theme.light.rawValue)
private static var appTheme: Int
func save() {
Theme.appTheme = self.rawValue
}
static var current: Theme {
Theme(rawValue: appTheme) ?? .light
}
}
Persister@propertyWrapper
struct Persist<T> {
let key: String
let defaultValue: T
var wrappedValue: T {
get { UserDefaults.standard.object(forKey: key) as? T ?? defaultValue }
set { UserDefaults.standard.set(newValue, forKey: key) }
}
init(key: String, defaultValue: T) {
self.key = key
self.defaultValue = defaultValue
}
}
Pour forcer la conception, vous devez modifier le style de toutes les fenêtres d'application.
Nous implémentons le changement de thème dans l'application.
extension Theme {
@available(iOS 13.0, *)
var userInterfaceStyle: UIUserInterfaceStyle {
switch self {
case .light: return .light
case .dark: return .dark
}
}
func setActive() {
save()
guard #available(iOS 13.0, *) else { return }
UIApplication.shared.windows
.forEach { $0.overrideUserInterfaceStyle = userInterfaceStyle }
}
}
Il est également nécessaire de changer le style de la fenêtre pour le thème actuel avant d'afficher la fenêtre.extension UIWindow {
func initTheme() {
guard #available(iOS 13.0, *) else { return }
overrideUserInterfaceStyle = Theme.current.userInterfaceStyle
}
}
Captures d'écran du choix d'un thème clair ou foncé Ajouter un commutateur au thème système
Ajoutez un thème système au thème enum.enum Theme: Int, CaseIterable {
case system = 0
case light
case dark
}
Après l'installation forcée d'un thème clair ou sombre, il est impossible de déterminer quel design est inclus dans le système. Pour reconnaître la conception du système, nous ajoutons une fenêtre à l'application, dans laquelle nous ne forcerons pas le changement de conception. Il est également nécessaire d'implémenter une modification de conception lorsque l'application a un thème système installé et que l'utilisateur modifie la conception dans iOS.final class ThemeWindow: UIWindow {
override public func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
if Theme.current == .system {
Theme.system.setActive()
}
}
}
let themeWindow = ThemeWindow()
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
...
themeWindow.makeKey()
...
return true
}
}
extension Theme {
@available(iOS 13.0, *)
var userInterfaceStyle: UIUserInterfaceStyle {
switch self {
case .light: return .light
case .dark: return .dark
case .system: return themeWindow.traitCollection.userInterfaceStyle
}
}
func setActive() {
save()
guard #available(iOS 13.0, *) else { return }
UIApplication.shared.windows
.filter { $0 != themeWindow }
.forEach { $0.overrideUserInterfaceStyle = userInterfaceStyle }
}
}
Captures d'écran du choix d'un système, d'un thème clair ou sombre Résultat
Prise en charge de la conception sombre et de la commutation entre les thèmes système, clair et sombre.Lien vers l'ensemble du projet