如何检查 iOS/iPadOS 中是不是启用了深色模式?
Posted
技术标签:
【中文标题】如何检查 iOS/iPadOS 中是不是启用了深色模式?【英文标题】:How can I check whether dark mode is enabled in iOS/iPadOS?如何检查 iOS/iPadOS 中是否启用了深色模式? 【发布时间】:2019-10-19 12:03:00 【问题描述】:从 ios/iPadOS 13 开始,可以使用深色用户界面样式,类似于 macOS Mojave 中引入的深色模式。如何检查用户是否启用了系统范围的暗模式?
【问题讨论】:
这个用户界面实际上是从 tvOS 10 和 iOS 12 开始可用的——在 iOS 12 上,它只是在辅助功能选项中作为“反转颜色”提供 Aaron Brager 的评论有些不准确 - 是的,您可以“反转颜色”,但它与打开暗模式有很大不同。它可能会给您的应用程序仍然可用的错误印象。例如:如果您无意中将系统颜色与您自己的颜色混合在一起,那么 invert 会反转所有这些颜色。但是,在暗模式下,系统颜色会改变,而你的不会。因此,就像 Touchgram v1.1.0 一样,您最终可以在非常淡蓝色的背景上获得近乎白色的文本。 App Store 评论不支持这个! 这里是 To check the current state,这是给 Observing for live changes of the state 的。两个答案都涵盖了 UIKit/AppKit/SwiftUI 等。 【参考方案1】:对于iOS 13,您可以使用此属性检查当前样式是否为深色模式:
if #available(iOS 13.0, *)
if UITraitCollection.current.userInterfaceStyle == .dark
print("Dark mode")
else
print("Light mode")
【讨论】:
如果您想签入 AppDelegate,这很好,因为它没有像UIViewController
这样的 traitCollection
变量
谢谢!最后确实是 AppDelegate 问题的正确答案:)
这对禁用的暗模式没有反应。如果你使用window?.overrideUserInterfaceStyle = .light
,那么UITraitCollection.current.userInterfaceStyle
可以返回.dark
。
这在我的情况下不起作用。使我的 iOS 应用程序支持 Mac。我的 mac mini 当前外观是暗的,在 appdelegate 文件中我有时会变亮,有时会变暗模式,而不是每次都进入暗模式。请帮帮我。【参考方案2】:
您应该检查UITraitCollection
的userInterfaceStyle
变量,与tvOS 和macOS 上相同。
switch traitCollection.userInterfaceStyle
case .light: //light mode
case .dark: //dark mode
case .unspecified: //the user interface style is not specified
您应该使用UIView
/UIViewController
的traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?)
函数来检测界面环境的变化(包括用户界面风格的变化)。
来自Apple Developer Documentation:
iOS界面环境变化时系统调用该方法。根据您的应用程序的需要,在视图控制器和视图中实现此方法,以响应此类更改。例如,当 iPhone 从纵向旋转到横向时,您可能会调整视图控制器的子视图的布局。该方法的默认实现为空。
系统默认 UI 元素(例如 UITabBar
或 UISearchBar
)会自动适应新的用户界面样式。
【讨论】:
除了traitCollectionDidChange(_:)
,您还可以检查UIView
的layoutSubviews()
、draw(_:)
、updateConstraints()
或tintColorDidChange()
或UIViewController
中的变化的updateViewConstraints()
、viewWillLayoutSubviews()
或viewDidLayoutSubviews()
。每次用户界面样式发生变化时,都会调用所有这些方法。
这将为您提供当前视图的用户界面样式。如果您为该特定视图覆盖了它,它不会告诉您系统的样式。【参考方案3】:
正如 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 类中的主题。【参考方案4】:在objective-c中你想做的:
if( self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark )
//is dark
else
//is light
【讨论】:
【参考方案5】:对于 Swift:
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 video
【讨论】:
我最终在我的 iOS 项目中将它用于 Xamarin.Forms。到目前为止最好的答案。 (消息灵通的可靠答案比 MS for Xamarin 的官方 doku 的一些博主的第 100 个副本更好。)@Pedro Trujillo 你救了我的一天。谢谢! 任何。 ios 11 版本?【参考方案6】:SwiftUI
使用Environment
变量的\.colorScheme
键:
struct ContentView: View
@Environment(\.colorScheme) var colorScheme
var body: some View
Text(colorScheme == .dark ? "In dark mode" : "In light mode")
此外,它会根据环境配色方案的变化自动更新。
UIKit
查看当前,所有符合UITraitEnvironment
协议的对象,包括所有UIView
子类和所有UIViewConttroller
子类都可以访问当前样式:
myUIView.traitCollection.userInterfaceStyle == .dark
myUIViewController.traitCollection.userInterfaceStyle == .dark
要检测风格的实时变化,here is the full detailed answer
【讨论】:
我在我的 ContentView 中使用了这个方法来改变 Tab Bar 界面的强调色。在标签视图的末尾,我使用了 .accentColor(colorScheme == .dark ? .green : .black) 当像这样声明@Enironement 时,我得到Type annotation missing in pattern
。【参考方案7】:
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,就不可能可靠地单独管理状态栏文本颜色。 请注意,这可能对某人有所帮助:如果您在info.plist
中将 UIUserInterfaceStyle
设置为 light
,则此方法将始终返回 light
@LeonidSilver 非常感谢!!!删除系统主题(.unspecified)的 info.plist 中的 UIUserInterfaceStyle 项!
对我来说,使用键盘扩展程序,UITraitCollection.current.userInterfaceStyle
在扩展程序启动时返回正确的值,但在我打开和关闭明暗模式时不会改变。【参考方案8】:
目标 C
要通过控制中心检测何时启用或禁用暗模式,请使用“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
【讨论】:
【参考方案9】:为第 1 次写入方法创建一个类函数并在任何你想要的地方使用
func isDarkMode() -> Bool
if #available(iOS 12.0, *)
if UIScreen.main.traitCollection.userInterfaceStyle == .dark
return true
else
return false
else
return false
【讨论】:
【参考方案10】:以下适用于任何 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 是关于学习的,而不是提供 sn-ps 来盲目复制和粘贴。请edit您的问题并解释它如何比OP提供的更好。 @Chris。感谢您的评论,但实际上这里的每个答案都是一个代码转储......这个问题非常简单,答案也是如此。感谢您指出这一点,我会添加更多解释 这不会使纯代码答案可接受。这条评论被标记为“低质量答案”,可能是因为它纯粹是代码,或者是“迟到的回复”(我不记得是哪个),我通过审查队列发表了评论。最好突出显示您更改的内容、更改原因以及您的答案如何改进现有答案。我数了十个早于你的答案。让你的脱颖而出。【参考方案11】:检测变化的最佳点是 UIView/UIViewController 的 traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) 函数。
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
【讨论】:
【参考方案12】: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 中使用 window,请从 SceneDelegate 调用 window
它类似于上面的大多数答案,但是当我们使用改变模式时,这会更好
window?.overrideUserInterfaceStyle = .dark
可以称为
isDarkMode ? .black : .white
【讨论】:
【参考方案13】:你可以使用这个扩展:
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
【讨论】:
【参考方案14】:也许有一些不错的扩展?
public extension UIViewController
@available(iOS 12.0, *)
public var isDarkMode: Bool traitCollection.userInterfaceStyle == .dark
【讨论】:
【参考方案15】:您可以使用此方法 Swift 5 轻松检测暗模式或亮模式
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
if traitCollection.userInterfaceStyle == .light
print("Light mode")
else
print("Dark mode")
【讨论】:
【参考方案16】:您可以使用以下代码检查项目中的明暗模式:
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
就像自 Mojave 以来在 macOS 中一样,您可以在资产目录中为明暗模式定义图像,以便自动使用这些图像:
【讨论】:
以上是关于如何检查 iOS/iPadOS 中是不是启用了深色模式?的主要内容,如果未能解决你的问题,请参考以下文章
如何检查 WordPress 中是不是启用了 XML-RPC
iOS/iPadOS 中的 SwiftUI + DocumentGroup:如何重命名当前打开的文档