[Swift 3.0]NSLayoutAnchorを用いたコードによるAuto Layout

  • 13
    Like
  • 0
    Comment

以前、Auto Layoutをコードで書いて、その考え方を知るという記事を書きました。
http://qiita.com/shindooo/items/f0259f1be59591503dc1

そのときはSwift 2.2で書いたのですが、Swift 3.0でAPIが一部変更されています(考え方は同じです)。

Swift 3の書き方でNSLayoutAnchorの使い方を再度まとめたいと思います。

Auto Layoutの考え方

Auto Layoutでは「制約(Constraint)」を設定することで、ビューの位置やサイズの決定します。

制約は、位置・サイズについてビュー同士の相対的な関係を定義したものです。
相対的な関係というのは

緑のビューの幅は、青のビューの幅を1.5倍して30pt加えた大きさである

というようなことです。

このことを数式で表すと次のようになります。

greenView.width = 1.5 × blueView.width + 30

さらに一般的に書くと

y = ax + b

簡単な一次関数ですね。この式は非常に重要であり、制約の本質を表しています。
制約を定義するということは、この式の各要素を指定するということになります。

事前準備

次のようにコードでビューを追加します。

let blueView = UIView()
blueView.backgroundColor = UIColor.blue
blueView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(blueView)

AutoresizingMaskをAuto Layoutに変換しないよう、translatesAutoresizingMaskIntoConstraintsをfalseにしておくとよいでしょう(このあと追加する制約とコンフリクトさせないため)。

NSLayoutAnchorを使う

では早速、NSLayoutAnchorを使った例を見てみましょう。

let leadingConstraint = blueView.leadingAnchor.constraint(equalTo:self.view.leadingAnchor, constant: 30.0)

上記は

青のビューの左端は、親ビューの左端から30ptの位置である

という制約です。

この制約を有効にするには以下のように

leadingConstraint.isActive = true

とします。
これは、つぎのように1行で書くこともできます。

blueView.leadingAnchor.constraint(equalTo:self.view.leadingAnchor, constant: 30.0).isActive = true

以下、簡単なサンプルを載せておきます。

ViewController.swift
override func viewDidLoad() {
    super.viewDidLoad()

    let blueView = UIView()
    blueView.backgroundColor = UIColor.blue
    blueView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(blueView)

    let greenView = UIView()
    greenView.backgroundColor = UIColor.green
    greenView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(greenView)

    // 青のビューの左端は、親ビューの左端から30ptの位置
    blueView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 30.0).isActive = true
    // 青のビューの縦方向の中心は、親ビューの縦方向の中心と同じ
    blueView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
    // 青のビューの幅は、親ビューの幅の1/4
    blueView.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.25).isActive = true
    // 青のビューの高さは30pt
    blueView.heightAnchor.constraint(equalToConstant: 30.0).isActive = true

    // 緑のビューの左端は、青のビューの右端から20ptの位置
    greenView.leadingAnchor.constraint(equalTo: blueView.trailingAnchor, constant: 20.0).isActive = true
    // 緑のビューの上端は、青のビューの上端と同じ位置
    greenView.topAnchor.constraint(equalTo: blueView.topAnchor).isActive = true
    // 緑のビューの幅は、青のビューの幅を1.5倍して30pt加えた大きさ
    greenView.widthAnchor.constraint(equalTo: blueView.widthAnchor, multiplier: 1.5, constant: 30.0).isActive = true
    // 緑のビューの高さは、青のビューの高さと同じ大きさ
    greenView.heightAnchor.constraint(equalTo: blueView.heightAnchor).isActive = true
}

ALS3.png