如何将安全区域添加到视图高度?

How can I add the safe area to the view height?

我正在创建一个顶部“横幅”,我希望它覆盖安全区域和更多区域。
我似乎找不到如何覆盖安全区域。

第一张图是想要的效果,第二张是刘海屏iPhone上的效果。

Desired Effect What's Happening

如何将安全区域添加到所需的高度值?

代码:

let shadowView = UIView( frame: CGRect( x: -10, y: -20, width: (view.frame.width+20), height: 90 ) )
        view.addSubview( shadowView )
        shadowView.backgroundColor = .clear
        shadowView.layer.shadowColor = UIColor.black.cgColor
        shadowView.layer.shadowOpacity = 0.3
        shadowView.layer.shadowOffset = CGSize(width: 5, height: 3)
        shadowView.layer.shadowRadius = 4.0
let titleView = UIView( frame: CGRect( x: 0, y: 0, width: ( shadowView.frame.width ), height: 90 ) )
        shadowView.addSubview( titleView )
        titleView.backgroundColor = .systemGreen
        titleView.layer.cornerRadius = 45
        titleView.layer.masksToBounds = true

问题出在这里:

let shadowView = UIView( frame: CGRect( x: -10, y: -20, width: (view.frame.width+20), height: 90 ) )

您正在对框架进行硬编码 - 不要这样做!好吧,90的高度就可以了。但是 x: -10, y: -20, width: (view.frame.width+20) 很糟糕。并非所有手机的尺寸都相同。

从技术上讲,您可以将安全区域插入高度计算为 ,但这仍然很糟糕。当用户旋转他们的设备并且刘海移动时会发生什么?听起来工作量很大。

你要的是Auto Layout and the Safe Area。使用自动布局,只需定义一些约束,然后观察您的 UIView 在所有屏幕尺寸上看起来都很棒。然后,安全区域定义屏幕的哪些部分是“安全的”,意思是“没有被凹口或圆角屏幕角覆盖”。

因此,您可以将 shadowView 固定到屏幕边缘(notch/safe 区域之外),并添加 .systemGreen 背景色。然后,将 titleView 设置为 90 点高,将其垂直固定到 shadowView。请注意 titleView.topAnchor 是如何固定到 shadowView.safeAreaLayoutGuide.topAnchor 的——这使得它远离缺口。

let shadowView = UIView() /// green background with shadow and corner radius
shadowView.translatesAutoresizingMaskIntoConstraints = false
shadowView.backgroundColor = .systemGreen /// put the background color here instead of on `titleView`, because this view stretches beyond the notch
shadowView.layer.shadowColor = UIColor.black.cgColor
shadowView.layer.shadowOpacity = 0.3
shadowView.layer.shadowOffset = CGSize(width: 5, height: 3)
shadowView.layer.shadowRadius = 4.0
shadowView.layer.cornerRadius = 45
shadowView.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner] /// only round the bottom corners
view.addSubview(shadowView)

let titleView = UIView() /// container for title label.
titleView.translatesAutoresizingMaskIntoConstraints = false
shadowView.addSubview(titleView)

let titleLabel = UILabel() /// the title label itself
titleLabel.translatesAutoresizingMaskIntoConstraints = false
titleView.addSubview(titleLabel)
titleLabel.text = "Catalogues"
titleLabel.font = UIFont.systemFont(ofSize: 36, weight: .medium)

NSLayoutConstraint.activate([
    
    /// constrain `shadowView`
    shadowView.topAnchor.constraint(equalTo: view.topAnchor),
    shadowView.rightAnchor.constraint(equalTo: view.rightAnchor),
    shadowView.leftAnchor.constraint(equalTo: view.leftAnchor),
    
    
    /// constrain `titleView`
    titleView.topAnchor.constraint(equalTo: shadowView.safeAreaLayoutGuide.topAnchor), /// most important part!
    titleView.heightAnchor.constraint(equalToConstant: 90), /// will also stretch `shadowView` vertically
    titleView.rightAnchor.constraint(equalTo: shadowView.rightAnchor),
    titleView.leftAnchor.constraint(equalTo: shadowView.leftAnchor),
    titleView.bottomAnchor.constraint(equalTo: shadowView.bottomAnchor),
    
    /// constrain `titleLabel`
    titleLabel.centerXAnchor.constraint(equalTo: titleView.centerXAnchor),
    titleLabel.centerYAnchor.constraint(equalTo: titleView.centerYAnchor)
])

结果:

iPhone 8 iPhone 12

为了进一步阅读,我有一个关于这个主题的blog post