如何分配视图的 UIUserInterfaceLevel?

How to assign a view's UIUserInterfaceLevel?

UITraitCollectionuserInterfaceLeveldocumentation 状态:

When you want parts of your UI to stand out from the underlying background, assign the UIUserInterfaceLevel.elevated level to them. For example, the system assigns the UIUserInterfaceLevel.elevated level to alerts and popovers.

你是怎么做到的?如果您尝试 myOverlayView.traitCollection.userInterfaceLevel = .elevated,您会收到错误消息“无法分配给 属性:'userInterfaceLevel' 是一个只获取 属性。”

我想知道是否有一个 属性 overrideUserInterfaceLevel 类似于 overrideUserInterfaceStyle 但可惜没有。

如前所述,无法覆盖 UITraitCollection 上的 userInterfaceLevel。不支持尝试覆盖 UIView 子类中的 traitCollection 变量。不幸的是,也没有办法像覆盖界面样式那样覆盖 UIView 上的界面级别。

有两个 API 可以在视图控制器级别覆盖特征集合,UIView 子视图继承:

这一定是文档所指的内容,因为警报和弹出窗口是表示控制器。

如果您以一种看起来提升但系统不会自动提升它的方式呈现视图控制器,您可以通过以下方式手动提升它:

let myViewController = MyViewController()
myViewController.modalPresentationStyle = .overFullScreen
myViewController.modalTransitionStyle = .crossDissolve
myViewController.presentationController?.overrideTraitCollection = UITraitCollection(userInterfaceLevel: .elevated)
present(myViewController, animated: true, completion: nil)

如果您想要提升的视图需要成为 non-elevated 视图控制器中的子视图,您似乎可以做的是为所需的提升视图创建一个视图控制器,将其添加为 child,将其视图作为子视图插入,并覆盖 child 的特征集合。但这并不总是可行的,例如,如果您正在使用您希望提升的输入附件视图。

如果您实际上无法提升视图,则可以手动为视图(及其子视图)着色,就好像它们已提升一样。为此,您可以解析特定特征集合的颜色,这应该是应用了提升的用户界面级别特征的视图的特征集合。我创建了这个 UIColor 扩展:

extension UIColor {
    func elevated(for view: UIView) -> UIColor {
        let elevatedTraitCollection = UITraitCollection(userInterfaceLevel: .elevated)
        return resolvedColor(with: UITraitCollection(traitsFrom: [view.traitCollection, elevatedTraitCollection]))
    }
}

使用方法:

overlayView.backgroundColor = .systemBackground.elevated(for: overlayView)

注意这个 returns 静态 UIColor 将不再动态响应颜色外观变化 - 例如,如果他们将用户界面样式从浅色模式更改为深色模式,颜色将不会自动更新。您需要使用更改后的特征集合再次手动解析颜色,如下所示:

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    
    if traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) {
        //update colors
    }
}