iOS9下代码创建约束

来源:互联网 发布:md5算法java实现 编辑:程序博客网 时间:2024/05/27 20:38

本文内容来自Easier Auto Layout: Coding Constraints in iOS 9

创建约束

The NSLayoutAnchor class is a factory class for creating NSLayoutConstraint objects using a fluent API.
NSLayoutAnchor是用来创建NSLayoutConstraint对象的工厂类。相对于原来创建约束的方法更简便。

// Creating constraints using NSLayoutConstraintNSLayoutConstraint(item: subview,                   attribute: .Leading,                   relatedBy: .Equal,                   toItem: view,                   attribute: .LeadingMargin,                   multiplier: 1.0,                   constant: 0.0).active = trueNSLayoutConstraint(item: subview,                   attribute: .Trailing,                   relatedBy: .Equal,                   toItem: view,                   attribute: .TrailingMargin,                   multiplier: 1.0,                   constant: 0.0).active = true// Creating the same constraints using Layout Anchorslet margins = view.layoutMarginsGuidesubview.leadingAnchor.constraintEqualToAnchor(margins.leadingAnchor).active = truesubview.trailingAnchor.constraintEqualToAnchor(margins.trailingAnchor).active = true

NSLayoutAnchor有三个子类:

  • NSLayoutXAxisAnchor
  • NSLayoutYAxisAnchor
  • NSLayoutDimension

例如,如下创建的约束:

// 1bookTextView.translatesAutoresizingMaskIntoConstraints = false// 2bookTextView.leadingAnchor.constraintEqualToAnchor(                view.leadingAnchor).active = truebookTextView.trailingAnchor.constraintEqualToAnchor(                view.trailingAnchor).active = truebookTextView.bottomAnchor.constraintEqualToAnchor(                view.bottomAnchor,                constant: -20).active = true// 3bookTextView.heightAnchor.constraintEqualToAnchor(                view.heightAnchor,

active设置为true,表示其马上生效。

View Layout Margins
所有的view都有一个layoutMarginsGuide属性。相对于View Layout Margins创建的约束,在其view的边缘会留下一些空白的距离。

// 1avatarView.translatesAutoresizingMaskIntoConstraints = false// 2avatarView.topAnchor.constraintEqualToAnchor(                view.topAnchor).active = true// 3avatarView.leadingAnchor.constraintEqualToAnchor(                view.layoutMarginsGuide.leadingAnchor).active = trueavatarView.trailingAnchor.constraintEqualToAnchor(                view.layoutMarginsGuide.trailingAnchor).active = true// 4avatarView.heightAnchor.constraintEqualToConstant(200).active = true

如下,avatarView在左右两侧会留下空白的距离:
View Layout Margins

View Controller Layout Guides
同view一样,view controller 都有一个top和bottom的layout guide

上图中,avatarView在状态栏的底部,但如果还有其他的透明的bars,例如导航栏和底部的tab bar,那么上面的avatarView,就会被遮挡住。

所以当给view controller的view的subviews,添加约束时,要约束到view controller的top guide的 bottom和bottom guide的top anchor

avatarView.topAnchor.constraintEqualToAnchor(       topLayoutGuide.bottomAnchor).active = truebookTextView.bottomAnchor.constraintEqualToAnchor(             bottomLayoutGuide.topAnchor,             constant: -20).active = true

效果如下:

效果

Readable Content Guide
上图中绿色的bookTextView,当前左右边缘对齐到屏幕的边缘,这样在iPad上显示时,非常不便于阅读。

使用 readable content guides,会根据size class来调整大小,这样会在边缘添加空白的距离,来跟适合阅读。

bookTextView.leadingAnchor.constraintEqualToAnchor(             view.readableContentGuide.leadingAnchor).active = truebookTextView.trailingAnchor.constraintEqualToAnchor(             view.readableContentGuide.trailingAnchor).active = true

在iPad横屏下,显示如下:

iPad横屏

Intrinsic Content Size
所有的view都有一个intrinsic content size, 如果设置了content size,就不用创建width 和 height 约束。
UILabel的Intrinsic Content Size由font和text决定
UIView默认的Intrinsic Content SizeUIViewNoIntrinsicMetric,表示的是没有大小。

设置AvatarView的UIViewNoIntrinsicMetric

override func intrinsicContentSize() -> CGSize {  return CGSize(width: UIViewNoIntrinsicMetric, height: 100)}

如果想要在app运行时改变 intrinsic content size,可以调用invalidateIntrinsicContentSize()方法来更新

设置ContentHuggingPriority和ContentCompressionResistancePriority

setContentHuggingPriority(_:forAxis:) takes a priority and an axis to determine how much a view wants to stretch. A high priority means that a view wants to stay the same size. A low priority allows the view to stretch.

setContentCompressionResistancePriority(_:forAxis:) also takes a priority and an axis. This method determines how much a view wants to shrink. A high priority means that a view tries not to shrink and a low priority means that the view can squish.

优先级大小在1到1000之间,1000是最高的,标准的优先值如下:

UILayoutPriorityRequired = 1000UILayoutPriorityDefaultHigh = 750UILayoutPriorityDefaultLow = 250

给chapterLabel设置优先级:

chapterLabel.setContentHuggingPriority(                  UILayoutPriorityRequired,                  forAxis: .Vertical)chapterLabel.setContentCompressionResistancePriority(                  UILayoutPriorityRequired,                  forAxis: .Vertical)

这样保证其不会被拉伸和压缩

Constraint Activation and Deactivation
根据不同的size class来active约束

override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {  super.traitCollectionDidChange(previousTraitCollection)  // 1  if traitCollection.horizontalSizeClass == .Regular {    // 2    NSLayoutConstraint.deactivateConstraints(compactConstraints)    NSLayoutConstraint.activateConstraints(regularConstraints)    // 3    socialMediaView.axis = .Horizontal  } else {    // 4    NSLayoutConstraint.deactivateConstraints(regularConstraints)    NSLayoutConstraint.activateConstraints(compactConstraints)    socialMediaView.axis = .Vertical  }}

traitCollectionDidChange(_:)方法会捕获trait collection的改变

更新Constraint
这里写图片描述

  • 所有的约束在updateConstraints()中被计算。This is where all priorities, compression resistance, hugging and intrinsic content size all come together in one complex algorithm.可以重写此方法来改变约束。
  • Views are then laid out in layoutSubviews(). If you need to access the correct view frame, you can override this.

如下:

override func updateConstraints() {  super.updateConstraints()  // 1  var aspectRatio: CGFloat = 1  if let image = image {    aspectRatio = image.size.width / image.size.height  }  // 2  aspectRatioConstraint?.active = false  aspectRatioConstraint =        imageView.widthAnchor.constraintEqualToAnchor(            imageView.heightAnchor,            multiplier: aspectRatio)  aspectRatioConstraint?.active = true}

手工布局view
Occasionally you’ll want to access a view’s frame. This can only safely be done in layoutSubviews() after all the views have been laid out by the Auto Layout engine.

override func layoutSubviews() {  super.layoutSubviews()  if bounds.height < socialMediaView.bounds.height {    socialMediaView.alpha = 0  } else {    socialMediaView.alpha = 1  }  if imageView.bounds.height < 30 {    imageView.alpha = 0  } else {    imageView.alpha = 1  }}
0 0
原创粉丝点击