iOS 13 引入UIImage了自动采用当前UIUserInterfaceStyle模式(又名亮或暗模式)的实例。但是,似乎只有从命名或系统映像(imageNamed:inBundle:withConfiguration:或systemImageNamed:withConfiguration:)构建此类映像的方法。
有没有办法UIImage从 Core Graphics动态生成通用明暗模式(例如使用两个CGImages 或使用 UIGraphicsImageRenderer)?
我没有看到任何 API,但也许我错了。
UITextField 有一个.placeholdertext 属性,用于在文本添加到字段之前显示信息,到目前为止它一直清晰可见,但在 iOS13 暗模式中引入,现在占位符文本在白色 UITextField 中几乎不可读(我明确表示通过.backgroundColor = [UIColor whiteColor])使其变白。
我的问题是,在我的整个项目中有哪些实用的解决方案可以解决这个问题,我可以手动更改任何 UITextField 上的占位符颜色,只需设置一个attributedPlaceholder字符串,这可能需要一段时间,有没有办法禁用暗模式设置专门针对 UITextFields 而不是针对其他元素?
所以......我试图根据苹果文档通过强制亮模式来设置我的应用程序以禁用iOS 13暗模式,在模拟器中所有尝试都可以正常工作,但是当我在真实设备上尝试时,没有任何反应,就像我一样我从来没有改变过我的代码
第一次尝试
覆盖窗口、视图或视图控制器的界面样式
我试图将此代码示例放在我的 viewDidLoad() 中
没有改变
if #available(iOS 13.0, *) {
overrideUserInterfaceStyle = .light
} else {
// Fallback on earlier versions
}
Run Code Online (Sandbox Code Playgroud)
第二次尝试
完全退出黑暗模式
系统会自动选择任何与 iOS 13.0 或更高版本 SDK 相关联的应用程序,以显示亮色和暗色外观。如果您需要额外的时间来处理应用程序的暗模式支持,您可以通过在应用程序的 Info.plist 文件中包含 UIUserInterfaceStyle 键(值为 Light)来暂时退出。将此键设置为 Light 会导致系统忽略用户的偏好并始终为您的应用程序应用浅色外观。
没有改变
如果有人知道我如何仅在浅色模式下设置我的应用程序......我将非常感激:D
我正在使用Xcode 11 beta的iOS 13进行工作。有什么方法可以在Web视图上支持暗模式吗?我为WKWebviews以外的所有其他视图创建了颜色集。如何在暗模式下更改Web视图的背景和文本颜色?
找不到解决方案,无法在iOS 13黑暗模式下更改所选日期的文本颜色。
我知道如何使用代码更改UIPicker视图的文本颜色
self.timePicker.setValue(UIColor.black, forKeyPath: "textColor")
Run Code Online (Sandbox Code Playgroud)
或使用用户定义的运行时属性。但是,无法为iOS 13深色模式更改所选日期颜色。使用背景白色和黑色文本颜色时,我的日期选择器视图如下所示:
因此,将文本颜色更改为黑色不会更改所选日期的文本颜色。它将所有其他文本颜色更改为黑色;但不是所选的。所选的保持白色,这是黑暗模式的默认设置。
某些 UI 设置无法在暗/亮模式下自动工作,因为UIColor. 例如shadow在图层中。因为我需要在明暗模式下删除和放置阴影,所以我需要在某个地方放置updateShadowIfNeeded()函数。我知道如何检测当前的模式:
func dropShadowIfNeeded() {
switch traitCollection.userInterfaceStyle {
case .dark: removeShadow()
case .light: dropShadowIfNotDroppedYet()
default: assertionFailure("Unknown userInterfaceStyle")
}
}
Run Code Online (Sandbox Code Playgroud)
现在我把这个函数放在 里面layoutSubviews,因为每次外观改变时它都会被调用:
override func layoutSubviews() {
super.layoutSubviews()
dropShadowIfNeeded()
}
Run Code Online (Sandbox Code Playgroud)
但是这个函数被调用了很多。只有在userInterfaceStyle更改时才触发的正确功能是什么?
在 iOS 上检查深色模式和浅色模式之间变化的标准方法是使用视图级委托函数:
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
switch self.traitCollection.userInterfaceStyle {
case .dark:
print("dark")
case .light:
print("light")
case .unspecified:
print("unspecified")
@unknown default:
fatalError()
}
}
Run Code Online (Sandbox Code Playgroud)
这很有效,但在具有 100 个视图控制器的应用程序中,向每个控制器添加此调用是一件痛苦的事情,而且很混乱。我想做的是通过NotificationCenter观察AppDelegate级别上明暗之间的变化。这样我就可以创建一个适用于所有视图的全局主题更改函数。
我在 AppDelegate.swift 中尝试了以下操作,但在暗/亮之间切换时,daytimeDidChange 永远不会被调用:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
NotificationCenter.default.addObserver(self, selector: #selector(daytimeDidChange), name: nil, object: UIScreen.main.traitCollection)
}
@objc func daytimeDidChange() {
if UITraitCollection.current.userInterfaceStyle == .dark {
//Dark
print("dark")
}
else {
//Light
print("light")
}
}
Run Code Online (Sandbox Code Playgroud)
关于如何正确设置通知观察者有什么想法吗?
Apple 建议我们使用traitCollectionDidChangehasDifferentColorAppearance 来使用和比较特征集合,以捕捉何时切换暗模式,并在需要时对其进行操作。像这样:
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
if #available(iOS 13.0, *) {
let hasUserInterfaceStyleChanged = previousTraitCollection?.hasDifferentColorAppearance(comparedTo: traitCollection) ?? false
if (hasUserInterfaceStyleChanged) {
//Update UI
}
}
}
Run Code Online (Sandbox Code Playgroud)
我用它来更新 UI,在暗模式和亮模式之间切换时清除一些缓存等。
出于某种原因traitCollectionDidChange,hasDifferentColorAppearance每次我的应用程序处于后台时都会触发并评估为 true,无论我是否在设备上启用了暗模式。在这种情况下,previousTraitCollection 和当前 traitCollection 似乎从来没有匹配的 interfaceStyles。如果 userInterfaceStyle 实际上没有改变,我宁愿避免在 userInterfaceStyle 改变时进行更新。
这是一个错误,还是我只是错过了什么?
我正在使用 Swift 5.1 和 Xcode 11.1,目前我已经完成了暗模式设计。
应用程序设置了用户可以设置显示主题(Light,Dark,System Default),目前如果应用程序在用户选择主题后重新启动,它可以正常工作(我将此 bool 数据保存在 UserDefaults 中,并在 AppDelegate 文件中的应用程序启动时设置 UIAppearance)
这是我的代码
if #available(iOS 13.0, *) {
switch AppState.appThemeStyle {
case "dark":
window?.overrideUserInterfaceStyle = .dark
break
case "light":
window?.overrideUserInterfaceStyle = .light
break
default:
window?.overrideUserInterfaceStyle = .unspecified
}
}
Run Code Online (Sandbox Code Playgroud)
但是我可以看到许多应用程序在用户设置主题样式后立即更改显示主题。
我认为仅更改主题而重新启动应用程序并不是一个好主意,并且在用户设置主题样式后应立即更改主题。
我试图通过在 ViewWillAppear 上设置基本视图控制器并设置用户界面样式来做到这一点,但导航栏和标签栏的外观没有改变。
谁能告诉我如何处理这个问题?谢谢。
ios-darkmode ×10
ios ×7
ios13 ×6
swift ×4
uikit ×2
objective-c ×1
swiftui ×1
uidatepicker ×1
uiimage ×1
uitextfield ×1
wkwebview ×1
xcode11 ×1