2017-09-20 59 views
23

因为我不使用故事板来创建我的视图,所以我想知道是否有编程的“使用安全区域指南”选项或类似的东西。以编程方式使用安全区域布局

我试图锚我的意见,以

view.safeAreaLayoutGuide

,但他们保持重叠在iPhone X模拟器的顶尖。

+0

没有记载布尔属性这个根据:https://developer.apple.com/documentation/uikit/uiview/positioning_content_relative_to_the_safe_area –

+0

怎么样'view.safeAreaInsets'?你试过这个吗? –

+0

@KarthikeyanBose是的,我很幸运没有运气。 – Phillip

回答

46

下面是示例代码(参考范围:Safe Area Layout Guide):
如果您创建约束代码中使用的UIView的safeAreaLayoutGuide属性来获取相关的布局锚。让我们重新上面的代码中Interface Builder的例子来看看它的外观:

假设我们有绿色的观点在我们的视图控制器属性:

private let greenView = UIView() 

我们可能有一个函数来设置的意见和从viewDidLoad中称为约束:

private func setupView() { 
    greenView.translatesAutoresizingMaskIntoConstraints = false 
    greenView.backgroundColor = .green 
    view.addSubview(greenView) 
} 

一如既往使用根视图的layoutMarginsGuide创建的前缘和后缘的约束:

let margins = view.layoutMarginsGuide 
    NSLayoutConstraint.activate([ 
     greenView.leadingAnchor.constraint(equalTo: margins.leadingAnchor), 
     greenView.trailingAnchor.constraint(equalTo: margins.trailingAnchor) 
]) 

现在,除非你是针对iOS的11只则需要使用#available包装安全区域布局指导约束和回落到顶部和底部布局指南较早的IOS版本:

if #available(iOS 11, *) { 
    let guide = view.safeAreaLayoutGuide 
    NSLayoutConstraint.activate([ 
    greenView.topAnchor.constraintEqualToSystemSpacingBelow(guide.topAnchor, multiplier: 1.0), 
    guide.bottomAnchor.constraintEqualToSystemSpacingBelow(greenView.bottomAnchor, multiplier: 1.0) 
    ]) 

} else { 
    let standardSpacing: CGFloat = 8.0 
    NSLayoutConstraint.activate([ 
    greenView.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: standardSpacing), 
    bottomLayoutGuide.topAnchor.constraint(equalTo: greenView.bottomAnchor, constant: standardSpacing) 
    ]) 
} 

结果:

enter image description here

enter image description here


这里是Safe Area Layout Guide


安全区苹果开发者官方文档需要处理的iPhone-X的用户界面设计。下面是How to design user interface for iPhone-X using Safe Area Layout

+1

也可以在Objective-C中给出这个吗?它看起来就像我需要的东西 –

+4

@TomHammond这里是在Objective-C为你https://stackoverflow.com/a/47076040/5638630 – Krunal

+0

我们应该真的通过操作系统检查,而不是通过设备检查?我的意思是这个代码'#available(iOS 11,*)' –

3

我用这个来代替加前缘和后缘约束到layoutMarginsGuide基本方针:

UILayoutGuide *safe = self.view.safeAreaLayoutGuide; 
yourView.translatesAutoresizingMaskIntoConstraints = NO; 
[NSLayoutConstraint activateConstraints:@[ 
              [safe.trailingAnchor constraintEqualToAnchor:yourView.trailingAnchor], 
              [yourView.leadingAnchor constraintEqualToAnchor:safe.leadingAnchor], 
              [yourView.topAnchor constraintEqualToAnchor:safe.topAnchor], 
              [safe.bottomAnchor constraintEqualToAnchor:yourView.bottomAnchor] 
              ]]; 

也请您查看选项从Krunal的回答较低版本的IOS 11。

+1

不工作......? – Nagarjun

+0

确保您已将您的视图添加到superView中。这是self.view在我的代码中作为一个简单的例子。 –

2

SafeAreaLayoutGuideUIView属性,

的safeAreaLayoutGuide的顶部指示视图的视野开阔顶部边缘 (例如,不背后 状态栏或导航栏,如果存在的话)。对于其他边缘也是如此。

使用safeAreaLayoutGuide避免我们的对象从圆角,导航栏,选项卡栏,工具栏和其他祖先视图剪切/重叠。

我们可以分别创建safeAreaLayoutGuide对象&设置对象约束。

约束的肖像+景观是 -

Portrait image

Landscape image

 self.edgesForExtendedLayout = []//Optional our as per your view ladder 

     let newView = UIView() 
     newView.backgroundColor = .red 
     self.view.addSubview(newView) 
     newView.translatesAutoresizingMaskIntoConstraints = false 
     if #available(iOS 11.0, *) { 
      let guide = self.view.safeAreaLayoutGuide 
      newView.trailingAnchor.constraint(equalTo: guide.trailingAnchor).isActive = true 
      newView.leadingAnchor.constraint(equalTo: guide.leadingAnchor).isActive = true 
      newView.topAnchor.constraint(equalTo: guide.topAnchor).isActive = true 
      newView.heightAnchor.constraint(equalToConstant: 100).isActive = true 

     } 
     else { 
      NSLayoutConstraint(item: newView, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1.0, constant: 0).isActive = true 
      NSLayoutConstraint(item: newView, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1.0, constant: 0).isActive = true 
      NSLayoutConstraint(item: newView, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1.0, constant: 0).isActive = true 

      newView.heightAnchor.constraint(equalToConstant: 100).isActive = true 
     } 

UILayoutGuide

safeAreaLayoutGuide

+0

永远不要在'viewDidAppear'中设置约束,除非你完全知道你在做什么。 'viewDidAppear'被多次调用,所以每次调用时你的约束都会被复制。 –

+0

是的! ,编辑答案,你可以用作你的用例。 – Jack

1

对于那些你们谁使用SnapKit,就像我一样,该解决方案是固定的约束view.safeAreaLayoutGuide像这样:

yourView.snp.makeConstraints { (make) in 
    if #available(iOS 11.0, *) { 
     //Bottom guide 
     make.bottom.equalTo(view.safeAreaLayoutGuide.snp.bottomMargin) 
     //Top guide 
     make.top.equalTo(view.safeAreaLayoutGuide.snp.topMargin) 
     //Leading guide 
     make.leading.equalTo(view.safeAreaLayoutGuide.snp.leadingMargin) 
     //Trailing guide 
     make.trailing.equalTo(view.safeAreaLayoutGuide.snp.trailingMargin) 

    } else { 
     make.edges.equalToSuperview() 
    } 
} 
+0

是的,现在我的代码变大了3倍 –

17

实际上,我使用它的扩展和控制,如果它是IOS 11与否。

extension UIView { 

    var safeTopAnchor: NSLayoutYAxisAnchor { 
    if #available(iOS 11.0, *) { 
     return self.safeAreaLayoutGuide.topAnchor 
    } else { 
     return self.topAnchor 
    } 
    } 

    var safeLeftAnchor: NSLayoutXAxisAnchor { 
    if #available(iOS 11.0, *){ 
     return self.safeAreaLayoutGuide.leftAnchor 
    }else { 
     return self.leftAnchor 
    } 
    } 

    var safeRightAnchor: NSLayoutXAxisAnchor { 
    if #available(iOS 11.0, *){ 
     return self.safeAreaLayoutGuide.rightAnchor 
    }else { 
     return self.rightAnchor 
    } 
    } 

    var safeBottomAnchor: NSLayoutYAxisAnchor { 
    if #available(iOS 11.0, *) { 
     return self.safeAreaLayoutGuide.bottomAnchor 
    } else { 
     return self.bottomAnchor 
    } 
    } 
} 
+0

不错,很酷的主意! – Phillip

0

以视觉格式使用约束,您可以免费获得对安全区域的尊重。

class ViewController: UIViewController { 

    var greenView = UIView() 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     greenView.backgroundColor = .green 
     view.addSubview(greenView) 
    } 
    override func viewWillLayoutSubviews() { 
     super.viewWillLayoutSubviews() 

     greenView.translatesAutoresizingMaskIntoConstraints = false 
     let views : [String:Any] = ["greenView":greenView] 
     view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-[greenView]-|", options: [], metrics: nil, views: views)) 
     view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-[greenView]-|", options: [], metrics: nil, views: views)) 
    } 
} 

result