【问题标题】:Darkmode and multiwindows / scenes暗模式和多窗口/场景
【发布时间】:2020-01-19 05:04:06
【问题描述】:

我正在尝试在多场景应用程序中实现 ios13 暗模式。

不幸的是,当我将一个场景拖到屏幕边缘上时,方法 traitCollectionDidChange 会被多次调用,但值总是不同,导致我的 UI 在暗模式和亮模式之间闪烁。

怎么了?

这是我的实现

func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {  
    super.traitCollectionDidChange(previousTraitCollection)  

    print("THEME instance: \(self)")  

    let currentTraitCollection = self.traitCollection  
    var hasUserInterfaceStyleChanged = false  
    hasUserInterfaceStyleChanged = previousTraitCollection.hasDifferentColorAppearanceCompared(to: currentTraitCollection)  

    print("THEME hasUserInterfaceStyleChanged = \(hasUserInterfaceStyleChanged ? "YES" : "NO")")  

    if hasUserInterfaceStyleChanged {  
        let userInterfaceStyle = currentTraitCollection.userInterfaceStyle // Either .unspecified, .light, or .dark  

        switch userInterfaceStyle {  
            case .unspecified:  
                print("THEME UIUserInterfaceStyleUnspecified")  
            case .light:  
                print("THEME UIUserInterfaceStyleLight")  
            case .dark:  
                print("THEME UIUserInterfaceStyleDark")  
            }  
    } else {  
        print("THEME NOT CHANGED")  
    }  

}  

这是控制台中记录的语句

当新场景出现时...

THEME instance: <MainControllerViewController: 0x117e55910>  
THEME hasUserInterfaceStyleChanged = YES  
THEME UIUserInterfaceStyleLight  

当添加的场景消失时...

THEME instance: <MainControllerViewController: 0x117e55910>  
THEME hasUserInterfaceStyleChanged = YES  
THEME UIUserInterfaceStyleDark  
THEME instance: <MainControllerViewController: 0x117e55910>  
THEME hasUserInterfaceStyleChanged = YES  
THEME UIUserInterfaceStyleLight  
THEME instance: <MainControllerViewController: 0x117e55910>  
THEME hasUserInterfaceStyleChanged = NO  
THEME NOT CHANGED  
THEME instance: <MainControllerViewController: 0x117e55910>  
THEME hasUserInterfaceStyleChanged = YES  
THEME UIUserInterfaceStyleDark  
THEME instance: <MainControllerViewController: 0x117e55910>  
THEME hasUserInterfaceStyleChanged = YES  
THEME UIUserInterfaceStyleLight  

与此同时,我没有更改为暗模式(总是亮)...所以我希望只是主题没有改变。

【问题讨论】:

  • 请参阅stackoverflow.com/questions/57993277/…,了解造成如此多明显特征变化的可能原因。
  • 看起来当场景被关闭时,iPadOS 内部想要在两个 userInterfaceStyles 中捕获屏幕,因此多次调用 traitCollectionDidChange()。通常,这种情况发生得相当快,您不应该看到它(更不用说注意到它了)。当 userInterfaceStyle 更改时,请注意您实际在做什么。不正确的任务会导致明暗模式的闪烁。我遇到了这个问题,因为我使用通知模式来更新多个视图控制器。做一些更直接的事情可以解决问题。
  • 是的,我已经解决了,但这就是原因!

标签: ios13 uitraitcollection ios-darkmode


【解决方案1】:

我在同样的问题上苦苦挣扎,我找到的解决方案在SceneDelegate

一个UIScene 有多个状态:

.foregroundActive
.foregroundInactive
.background
.unattached

当您在幻灯片中调整窗口大小时,或者在这种情况下,从幻灯片中移除一个窗口,traitCollectionDidChange 会为每个窗口调用。这意味着您正在为处于.background.foregroundInactive.unattached 状态的场景更新userInterfaceStyle。这就是导致闪烁的原因。

解决方案是不使用traitCollectionDidChange,而是使用SceneDelegate 中的委托方法windowScene(_:didUpdate:interfaceOrientation:traitCollection:)

Apple's docs这个方法:

当场景的大小、方向或特征发生变化时通知您。

这样做的额外好处是我们可以在更新userInterfaceStyle之前检查场景的.activationState

    func windowScene(_ windowScene: UIWindowScene, didUpdate previousCoordinateSpace: UICoordinateSpace, interfaceOrientation previousInterfaceOrientation: UIInterfaceOrientation, traitCollection previousTraitCollection: UITraitCollection) {

          let currentTraitCollection = windowScene.traitCollection

          if windowScene.activationState == .foregroundActive {
             if currentTraitCollection.userInterfaceStyle != previousTraitCollection.userInterfaceStyle {
                 if currentTraitCollection.userInterfaceStyle == .light {
                     //update to light theme
                 } else {
                     //update to dark theme
                 }
             }
         }
     }

【讨论】:

    猜你喜欢
    • 2022-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多