Начиная с iOS/iPadOS 13 доступен темный стиль пользовательского интерфейса, аналогичный темному режиму, представленному в macOS Mojave. Как я могу проверить, включил ли пользователь общесистемный темный режим?
Комментарий Аарона Брагера несколько неточен — да, вы можете «инвертировать цвета», но это сильно отличается от включения темного режима. Это может создать ложное впечатление, что ваше приложение все еще можно использовать. например: если вы непреднамеренно смешали системные цвета со своими собственными, функция инвертирования инвертирует их все. Однако в темном режиме системные цвета изменятся, а ваши — нет. Таким образом, как и в случае с Touchgram v1.1.0, вы можете получить почти белый текст на очень бледно-голубом фоне. В обзоре App Store это НЕ указано!
Вот Чтобы проверить текущее состояние, а это для Наблюдение за живыми изменениями состояния. Оба ответа охватывают UIKit/AppKit/SwiftUI и т. д.
Вы должны проверить переменную userInterfaceStyle
для UITraitCollection
, как и в tvOS и macOS.
switch traitCollection.userInterfaceStyle {
case .light: //light mode
case .dark: //dark mode
case .unspecified: //the user interface style is not specified
}
Вы должны использовать функцию traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?)
UIView
/UIViewController
для обнаружения изменений в среде интерфейса (включая изменения в стиле пользовательского интерфейса).
Из Документация для разработчиков Apple:
The system calls this method when the iOS interface environment changes. Implement this method in view controllers and views, according to your app’s needs, to respond to such changes. For example, you might adjust the layout of the subviews of a view controller when an iPhone is rotated from portrait to landscape orientation. The default implementation of this method is empty.
Элементы пользовательского интерфейса по умолчанию (например, UITabBar
или UISearchBar
) автоматически адаптируются к новому стилю пользовательского интерфейса.
В дополнение к traitCollectionDidChange(_:)
вы также можете проверить изменение в UIView
, layoutSubviews()
, draw(_:)
или updateConstraints()
или в tintColorDidChange()
, UIViewController
или updateViewConstraints()
. Все эти методы вызываются каждый раз при изменении стиля пользовательского интерфейса.
Это даст вам стиль пользовательского интерфейса текущего представления. Если вы переопределили его для этого конкретного представления, он не скажет вам стиль системы.
Как упоминал daveextreme, проверка стиля пользовательского интерфейса текущего представления не всегда возвращает системный стиль при использовании свойства overrideUserInterfaceStyle
. В таких случаях может быть лучше использовать следующий код:
switch UIScreen.main.traitCollection.userInterfaceStyle {
case .light: //light mode
case .dark: //dark mode
case .unspecified: //the user interface style is not specified
}
Этот ответ лучше всего подходит для проверки темы в классе, отличном от UIViewController.
Лучшей точкой для обнаружения изменений является функция traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) UIView/UIViewController.
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
}
Обнаружение изменений внешнего вида является тривиальным путем переопределения traitCollectionDidChange на контроллерах представления. Затем просто получите доступ к traitCollection.userInterfaceStyle контроллера представления.
Однако важно помнить, что traitCollectionDidChange может вызываться для других изменений свойств, таких как вращение устройства. Вы можете проверить, отличается ли текущий внешний вид, используя этот новый метод:
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
let hasUserInterfaceStyleChanged = previousTraitCollection.hasDifferentColorAppearance(comparedTo: traitCollection) // Bool
// Update your user interface based on the appearance
}
в target-c вы хотели бы сделать:
if ( self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark ){
//is dark
}else{
//is light
}
Вы можете использовать это расширение:
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
}
}
Для iOS 13 вы можете использовать это свойство, чтобы проверить, является ли текущий стиль темным режимом или нет:
if #available(iOS 13.0, *) {
if UITraitCollection.current.userInterfaceStyle == .dark {
print("Dark mode")
}
else {
print("Light mode")
}
}
Это здорово, если вы хотите проверить AppDelegate, так как у него нет переменной traitCollection
, такой как UIViewController
Спасибо! Наконец-то действительно правильный ответ на проблему AppDelegate :)
Это не реагирует на отключенный темный режим. Если вы используете window?.overrideUserInterfaceStyle = .light
, то UITraitCollection.current.userInterfaceStyle
может вернуться .dark
.
Это не работает в моем случае. Сделать мое приложение iOS для Mac поддерживаемым. Текущий внешний вид моего mac mini темный, в файле appdelegate я иногда получаю светлый, а иногда темный режим, а не каждый раз темный режим. Пожалуйста помогите.
1/для UIView/UIViewController:
self.traitCollection.userInterfaceStyle == .dark
2/ для статического или другого:
UITraitCollection.current.userInterfaceStyle == .dark
НО:
//Never use this! You will get wrong value in app extensions (ex. ToDay widget)
UIScreen.main.traitCollection.userInterfaceStyle == .dark //WRONG!
На самом деле последний (UIScreen...) был единственным способом получить настройку темного режима пользователя в настройках устройства после переопределения userInterfaceStyle в моем приложении. Таким образом, я смог реализовать кнопку «следить за темным режимом iOS», которая немедленно обновляет цветовую тему приложения, даже если у меня есть пользовательские темы и выбор помимо этого. К сожалению, надежное управление цветом текста строки состояния по отдельности невозможно без переопределения userInterfaceStyle.
Обратите внимание, что это может кому-то помочь: если вы установили UIUserInterfaceStyle
в light
в своем info.plist
, эти методы всегда будут возвращать light
@LeonidSilver Большое спасибо!!! Удалите элемент UIUserInterfaceStyle в info.plist для системной темы (.unspecified), используя!
Для меня, используя расширение клавиатуры, UITraitCollection.current.userInterfaceStyle
возвращает правильное значение при запуске расширения, но никогда не меняется, когда я включаю и выключаю светлый и темный режимы.
Цель С
Чтобы определить, когда темный режим включен или отключен через Центр управления, используйте уведомление «appDidBecomeActive», которое будет запущено, когда вы вернетесь в свое приложение.
//----------------------------------------------------------------------------
// viewWillAppear
//----------------------------------------------------------------------------
- (void)viewWillAppear {
[super viewWillAppear];
[[NSNotificationCenter defaultCenter]addObserver:self
selector:@selector(appDidBecomeActive:)
name:UIApplicationDidBecomeActiveNotification
object:nil];
}
Не забудьте удалить его, когда закончите:
//------------------------------------------------------------------------------------
// viewWillDisappear
//------------------------------------------------------------------------------------
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIApplicationDidBecomeActiveNotification
object:nil];
}
Делайте все, что вам нужно, когда меняется темный режим:
//----------------------------------------------------------------------------
// 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
}
}
Создайте функцию класса для метода записи 1 раз и используйте везде, где хотите
func isDarkMode() -> Bool{
if #available(iOS 12.0, *) {
if UIScreen.main.traitCollection.userInterfaceStyle == .dark {
return true
} else {
return false
}
} else {
return false
}
}
Для Свифта:
if #available(iOS 12.0, *) {
switch UIScreen.main.traitCollection.userInterfaceStyle {
case .dark: // put your dark mode code here
case .light:
case .unspecified:
}
}
Для цели C:
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;
}
}
Для получения дополнительной информации смотрите этот WWDC2019 видео
В итоге я использовал его для Xamarin.Forms в своем проекте iOS. Безусловно, лучший ответ там. (хороший информированный надежный ответ, работающий лучше, чем сотая копия какого-то блоггера официального документа MS для Xamarin.) @Pedro Trujillo, вы спасли мой день. Спасибо!
Любые. иос 11 версия?
Может быть, какое-нибудь хорошее расширение?
public extension UIViewController {
@available(iOS 12.0, *)
public var isDarkMode: Bool { traitCollection.userInterfaceStyle == .dark }
}
Вспомогательный метод ниже, который работает на любой версии iOS:
var isDarkMode: Bool {
guard #available(iOS 12.0, *) else {
return false
}
return UIScreen.main.traitCollection.userInterfaceStyle == .dark
}
Применение:
view.backgroundColor = isDarkMode ? .black : .white
Добро пожаловать в Stack Overflow. Дампы кода без каких-либо объяснений редко бывают полезными. Stack Overflow предназначен для обучения, а не для слепого копирования и вставки фрагментов. Пожалуйста, редактировать свой вопрос и объясните, как он работает лучше, чем то, что предоставил OP.
@Крис. Спасибо за комментарий, но буквально каждый ответ здесь — дамп кода... Вопрос очень простой, как и ответ. Спасибо, что указали на это, я добавлю больше объяснений
Это не делает ответы только для кода приемлемыми. Этот комментарий был помечен либо как «ответ низкого качества», вероятно, потому, что это был чисто код, либо как «поздний ответ» (я не могу вспомнить какой), и я прокомментировал через очередь проверки. Всегда лучше указать, что вы изменили, почему вы изменили это и как ваш ответ улучшает любые существующие. Я насчитал десять ответов, предшествующих вашим. Сделайте свой выделиться.
Вы можете легко обнаружить темный режим или светлый режим с помощью этого метода Swift 5
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if traitCollection.userInterfaceStyle == .light {
print("Light mode")
} else {
print("Dark mode")
}}
С ключом \.colorScheme
переменной Environment
:
struct ContentView: View {
@Environment(\.colorScheme) var colorScheme
var body: some View {
Text(colorScheme == .dark ? "In dark mode" : "In light mode")
}
}
Кроме того, он автоматически обновляется при изменении цветовой схемы среды.
Чтобы проверить текущий, все объекты, соответствующие протоколу UITraitEnvironment
, включая все подклассы UIView
и все подклассы UIViewConttroller
, имеют доступ к текущему стилю:
myUIView.traitCollection.userInterfaceStyle == .dark
myUIViewController.traitCollection.userInterfaceStyle == .dark
Чтобы обнаружить живые изменения стиля, вот полный подробный ответ
Я использовал этот метод в своем ContentView, чтобы изменить цвет акцента интерфейса панели вкладок. В конце представления вкладок я использовал .accentColor(colorScheme == .dark ? .green : .black)
Я получаю Type annotation missing in pattern
, когда так объявляю @Enironement.
Вы можете использовать следующий код для проверки светлого или темного режима в вашем проекте:
func viewDidLoad() {
super.viewDidLoad()
switch traitCollection.userInterfaceStyle {
case .light, .unspecified:
// light mode detected
case .dark:
// dark mode detected
}
}
Вы также можете проверить изменения в стиле интерфейса:
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
}
Как и в macOS начиная с Mojave, вы можете определить изображения как для светлого, так и для темного режима в своем каталоге активов, чтобы эти изображения использовались автоматически:
var isDarkMode: Bool {
guard #available(iOS 12.0, *) else {
return false
}
let window = (UIApplication.shared.delegate as? AppDelegate)?.window
return window?.traitCollection.userInterfaceStyle == .dark
}
если вы не используете окно в AppDelegate, вызовите окно из SceneDelegate
Это похоже на большинство ответов выше, но это работает лучше, когда мы меняем режимы, используя
window?.overrideUserInterfaceStyle = .dark
можно назвать как
isDarkMode ? .black : .white
Этот пользовательский интерфейс фактически был доступен с tvOS 10 и iOS 12 — в iOS 12 он был просто доступен как «инвертировать цвета» в параметрах специальных возможностей.