幅と高さは、プログラムで自動レイアウトを使用したsuperViewと同じですか?


83

ネットでたくさんのスニペットを探していましたが、まだ問題の答えが見つかりません。私の質問は、scrollView(SV)があり、scrollView(SV)内に、スクロールビュー(SV)であるスーパービューと同じ幅と高さのボタンをプログラムで追加して、ユーザーが回転したときにデバイスボタンが同じフレームになるようにしたいということです。 scrollView(SV)の。NSLayout / NSLayoutConstraintを行う方法は?ありがとう

回答:


125

誰かがSwiftソリューションを探している場合–サブビューフレームをそのスーパービュー境界にバインドするたびに役立つSwift拡張機能をUIView作成します。

スウィフト2:

extension UIView {

    /// Adds constraints to this `UIView` instances `superview` object to make sure this always has the same size as the superview.
    /// Please note that this has no effect if its `superview` is `nil` – add this `UIView` instance as a subview before calling this.
    func bindFrameToSuperviewBounds() {
        guard let superview = self.superview else {
            print("Error! `superview` was nil – call `addSubview(view: UIView)` before calling `bindFrameToSuperviewBounds()` to fix this.")
            return
        }

        self.translatesAutoresizingMaskIntoConstraints = false
        superview.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[subview]-0-|", options: .DirectionLeadingToTrailing, metrics: nil, views: ["subview": self]))
        superview.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[subview]-0-|", options: .DirectionLeadingToTrailing, metrics: nil, views: ["subview": self]))
    }

}

スウィフト3:

extension UIView {

    /// Adds constraints to this `UIView` instances `superview` object to make sure this always has the same size as the superview.
    /// Please note that this has no effect if its `superview` is `nil` – add this `UIView` instance as a subview before calling this.
    func bindFrameToSuperviewBounds() {
        guard let superview = self.superview else {
            print("Error! `superview` was nil – call `addSubview(view: UIView)` before calling `bindFrameToSuperviewBounds()` to fix this.")
            return
        }

        self.translatesAutoresizingMaskIntoConstraints = false
        superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self]))
        superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self]))
    }
}

Swift 4.2:

extension UIView {

    /// Adds constraints to this `UIView` instances `superview` object to make sure this always has the same size as the superview.
    /// Please note that this has no effect if its `superview` is `nil` – add this `UIView` instance as a subview before calling this.
    func bindFrameToSuperviewBounds() {
        guard let superview = self.superview else {
            print("Error! `superview` was nil – call `addSubview(view: UIView)` before calling `bindFrameToSuperviewBounds()` to fix this.")
            return
        }

        self.translatesAutoresizingMaskIntoConstraints = false
        self.topAnchor.constraint(equalTo: superview.topAnchor, constant: 0).isActive = true
        self.bottomAnchor.constraint(equalTo: superview.bottomAnchor, constant: 0).isActive = true
        self.leadingAnchor.constraint(equalTo: superview.leadingAnchor, constant: 0).isActive = true
        self.trailingAnchor.constraint(equalTo: superview.trailingAnchor, constant: 0).isActive = true

    }
}

次に、単にこのように呼び出します

// after adding as a subview, e.g. `view.addSubview(subview)`
subview.bindFrameToSuperviewBounds()

.xibを使用してカスタムUIViewを作成する場合、bindFrameToSuperviewBoundsは、self.addSubview(self.view)
user1603721 2017

ビジュアルフォーマットを使用したソリューションは、安全なエリアフレンドリーではないことに注意してください。たとえば、ナビゲーションコントローラー内にあるビューでナビゲーションバーとツールバーを表示している場合、ビューはナビゲーションバーの下に表示され、さらに下に移動するとツールバーの下に表示されます。
Andy Ibanez

これはSwift5のソリューションとしても機能します。AutoLayoutを使用してカスタムサブビューをparentViewサイズに適合させることができませんでした。サブビューが追加されたらこれを使用すると、魅力として機能します。
toni_piu

Swift4.2ソリューションはうまく機能します。constant: 0パーツを外せば少し短くすることもできます。
Zyphrax

69

これが最も効率的な方法かどうかはわかりませんが、機能します。

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.translatesAutoresizingMaskIntoConstraints = NO;
// initialize


[coverForScrolView addSubview:button];

NSLayoutConstraint *width =[NSLayoutConstraint
                                    constraintWithItem:button
                                    attribute:NSLayoutAttributeWidth
                                    relatedBy:0
                                    toItem:coverForScrolView
                                    attribute:NSLayoutAttributeWidth
                                    multiplier:1.0
                                    constant:0];
NSLayoutConstraint *height =[NSLayoutConstraint
                                     constraintWithItem:button
                                     attribute:NSLayoutAttributeHeight
                                     relatedBy:0
                                     toItem:coverForScrolView
                                     attribute:NSLayoutAttributeHeight
                                     multiplier:1.0
                                     constant:0];
NSLayoutConstraint *top = [NSLayoutConstraint
                                   constraintWithItem:button
                                   attribute:NSLayoutAttributeTop
                                   relatedBy:NSLayoutRelationEqual
                                   toItem:coverForScrolView
                                   attribute:NSLayoutAttributeTop
                                   multiplier:1.0f
                                   constant:0.f];
NSLayoutConstraint *leading = [NSLayoutConstraint
                                       constraintWithItem:button
                                       attribute:NSLayoutAttributeLeading
                                       relatedBy:NSLayoutRelationEqual
                                       toItem:coverForScrolView
                                       attribute:NSLayoutAttributeLeading
                                       multiplier:1.0f
                                       constant:0.f];
[coverForScrolView addConstraint:width];
[coverForScrolView addConstraint:height];
[coverForScrolView addConstraint:top];
[coverForScrolView addConstraint:leading];

4
使用する方がはるかに効率的ですNSLayoutConstraint.activateConstraints([width, height, top, leading])
Berik 2015

使用できます[coverForScrolView addConstraints:@[width, height, top, leading]];
イスラムQ.

1
(数年後)このコードは非常に古くなっていることに注意してください。制約を追加するのがはるかに簡単になりました-以下の2017年の回答を参照してください
Fattie

49

このリンクはあなたを助けることができます、指示に従ってください:http//www.raywenderlich.com/20881/beginning-auto-layout-part-1-of-2

編集:

次のコードスニペットを使用します。ここで、サブビューはサブビューです。

[subview setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"H:|-0-[subview]-0-|"
                           options:NSLayoutFormatDirectionLeadingToTrailing
                           metrics:nil
                           views:NSDictionaryOfVariableBindings(subview)]];
[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"V:|-0-[subview]-0-|"
                           options:NSLayoutFormatDirectionLeadingToTrailing
                           metrics:nil
                           views:NSDictionaryOfVariableBindings(subview)]];

4
この場合、視覚的な形式も次のようにV:|[subview]|なりますH:|[subview]|
Gustavo Barbosa

4
(数年後)このコードは非常に古くなっていることに注意してください。制約を追加するのがはるかに簡単になりました-以下の2017年の回答を参照してください
Fattie

18

addConstraintそして、removeConstraintUIViewのための方法は、「制約の作成便利」を使用することの価値があるので、廃止される予定です。

view.topAnchor.constraint(equalTo: superView.topAnchor, constant: 0).isActive = true
view.bottomAnchor.constraint(equalTo: superView.bottomAnchor, constant: 0).isActive = true
view.leadingAnchor.constraint(equalTo: superView.leadingAnchor, constant: 0).isActive = true
view.trailingAnchor.constraint(equalTo: superView.trailingAnchor, constant: 0).isActive = true

これはうまく機能します。constant: 0パーツを外せば少し短くすることもできます。
Zyphrax

8

アプローチ#1:UIView拡張機能を介して

ここのより機能的にアプローチスイフト3+との前提条件の代わりに、print(コンソールで容易に死ぬことができます)。これは、失敗したビルドとしてプログラマーエラー報告します。

この拡張機能をプロジェクトに追加します。

extension UIView {
    /// Adds constraints to the superview so that this view has same size and position.
    /// Note: This fails the build if the `superview` is `nil` – add it as a subview before calling this.
    func bindEdgesToSuperview() {
        guard let superview = superview else {
            preconditionFailure("`superview` was nil – call `addSubview(view: UIView)` before calling `bindEdgesToSuperview()` to fix this.")
        }
        translatesAutoresizingMaskIntoConstraints = false
        ["H:|-0-[subview]-0-|", "V:|-0-[subview]-0-|"].forEach { visualFormat in
            superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: visualFormat, options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self]))
        }
    }
}

、それをこのように単に呼んでください:

// after adding as a subview, e.g. `view.addSubview(subview)`
subview.bindEdgesToSuperview()

上記のメソッドはすでに私のHandyUIKitフレームワークに統合されており、プロジェクトにさらに便利なUIヘルパーが追加れていることに注意してください。


アプローチ#2:フレームワークの使用

あなたがいる場合、プログラム制約でたくさんの仕事、プロジェクト内の私がチェックアウトすることをお勧めいたしますSnapKitを。これにより、制約の操作がはるかに簡単になりエラーが発生しにくくなります。

ドキュメントのインストール手順に従って、SnapKitをプロジェクトに含めます。次に、Swiftファイルの先頭にインポートします。

import SnapKit

今、あなたはこれだけで同じことを達成することができます:

subview.snp.makeConstraints { make in
    make.edges.equalToSuperview()
}

6

スウィフト3:

import UIKit

extension UIView {

    func bindFrameToSuperviewBounds() {
        guard let superview = self.superview else {
            print("Error! `superview` was nil – call `addSubview(view: UIView)` before calling `bindFrameToSuperviewBounds()` to fix this.")
            return
        }

        self.translatesAutoresizingMaskIntoConstraints = false
        superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self]))
        superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self]))
    }

}

Swift 3に準拠するようにコードを変更しただけの場合は、新しい回答を投稿するのではなく、元の投稿者の回答を編集する必要があります(これは元の投稿者の意図の変更ではないため)。編集するのに十分なポイントがない場合は、Swift 3に準拠するために必要な変更のヒントを使用して、元の投稿にコメントします。元の投稿者(またはコメントを見た他の人)がおそらく回答を更新します。このようにして、重複した回答や非推奨のコードからスレッドをクリーンに保ちます。
Jeehut 2016

ねえ@ Dschee-私はあなたに完全に同意しますが、私たちは「間違っています」。サイトの「コンセンサス」ビューは、良くも悪くも、ここで表現するものとは逆です。 meta.stackoverflow.com/questions/339024/… (私はコンセンサスの決定を絶えず無視し、賢明なことをしてから、改造からトラブルに巻き込まれます:))
Fattie 2017年

2

Swift 4の使用NSLayoutConstraint

footerBoardImageView.translatesAutoresizingMaskIntoConstraints = false
let widthConstraint  = NSLayoutConstraint(item: yourview, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: superview, attribute: NSLayoutAttribute.width, multiplier: 1, constant: 0)
let heightConstraint = NSLayoutConstraint(item: yourview, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: superview, attribute: NSLayoutAttribute.height, multiplier: 1, constant: 0)
superview.addConstraints([widthConstraint, heightConstraint])

1

補足的な答えとして、そしてサードパーティのライブラリを含めることに反対しない人のための答えとして、PureLayoutライブラリはまさにこれを行う方法を提供します。ライブラリをインストールすると、次のように簡単になります。

myView.autoPinEdgesToSuperviewEdges()

好みに応じて同様の機能を提供できる他のライブラリもあります。組積造地図作成


0

@Dscheeのソリューションのフォローアップとして、ここにswift 3.0構文があります:(注意:これは私のソリューションではありません。Swift3.0用に修正したばかりです)

extension UIView {

    /// Adds constraints to this `UIView` instances `superview` object to make sure this always has the same size as the superview.
    /// Please note that this has no effect if its `superview` is `nil` – add this `UIView` instance as a subview before calling this.
    func bindFrameToSuperviewBounds() {
        guard let superview = self.superview else {
            print("Error! `superview` was nil – call `addSubview(view: UIView)` before calling `bindFrameToSuperviewBounds()` to fix this.")
            return
        }

        self.translatesAutoresizingMaskIntoConstraints = false
        superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self]))
    superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self]))
}

1
Swift 3に準拠するようにコードを変更しただけの場合は、新しい回答を投稿するのではなく、元の投稿者の回答を編集する必要があります(これは元の投稿者の意図の変更ではないため)。編集するのに十分なポイントがない場合は、Swift 3に準拠するために必要な変更のヒントを使用して、元の投稿にコメントします。元の投稿者(またはコメントを見た他の人)がおそらく回答を更新します。このようにして、重複した回答や非推奨のコードからスレッドをクリーンに保ちます。
Jeehut 2016

私は、完全にあなたと@Dscheeを同意するが、そこにある(私には、不合理な)メタのコメントは...「我々はSO上でそれをしない」というmeta.stackoverflow.com/questions/339024/...
Fattie

@JoeBlowあなたのリンクの背後にある議論を読んだ後、私は実際にこれも理にかなっていると思います。私はPatrickHaughのコメント(質問に対する)に同意しますが、元の回答に対するコメントと組み合わせて新しい回答を与える必要があります。(将来の賛成を得るために)彼の答えを更新するかどうかは、元の投稿者次第です。リンクありがとうございます!
Jeehut 2017年

ええと、これは私が過去に忠実なヒットとランナーであり続けた理由のすべての大きな部分です。私は自分の答えをつかみ、それを現在の構文に変換して、コーディングを続けます。私がこのように投稿した主な理由は、swiftを教えたときに、新しいコーダーが関数宣言の更新に問題を抱えていたため、現在のバージョンのswiftで解決策を見つける方法についてよく尋ねられたためです。これは、フラストレーションの主な原因の1つでしたが、2つのコードスタイルを対比する機会でもありました。その結果、学生は他のコードスニペットで同様の変化を予測することができました。
James Larcombe 2017年

0

私はスーパービューを完全にカバーする必要がありました。他のものは、向きの変更中にそれをしません。そこで、20の任意のサイズの乗数を使用して、新しいものを作成しました。必要に応じて自由に変更してください。また、これは実際にはサブビューをスーパービューよりもはるかに大きくし、要件とは異なる可能性があることに注意してください。

extension UIView {
    func coverSuperview() {
        guard let superview = self.superview else {
            assert(false, "Error! `superview` was nil – call `addSubview(_ view: UIView)` before calling `\(#function)` to fix this.")
            return
        }
        self.translatesAutoresizingMaskIntoConstraints = false
        let multiplier = CGFloat(20.0)
        NSLayoutConstraint.activate([
            self.heightAnchor.constraint(equalTo: superview.heightAnchor, multiplier: multiplier),
            self.widthAnchor.constraint(equalTo: superview.widthAnchor, multiplier: multiplier),
            self.centerXAnchor.constraint(equalTo: superview.centerXAnchor),
            self.centerYAnchor.constraint(equalTo: superview.centerYAnchor),
            ])
    }
}

0

私は他の答えから最高の要素を選びました:

extension UIView {
  /// Adds constraints to this `UIView` instances `superview` object to make sure this always has the same size as the superview.
  /// Please note that this has no effect if its `superview` is `nil` – add this `UIView` instance as a subview before calling this.
  func bindFrameToSuperviewBounds() {
    guard let superview = self.superview else {
      print("Error! `superview` was nil – call `addSubview(view: UIView)` before calling `bindFrameToSuperviewBounds()` to fix this.")
      return
    }

    self.translatesAutoresizingMaskIntoConstraints = false

    NSLayoutConstraint.activate([
      self.topAnchor.constraint(equalTo: superview.topAnchor),
      self.bottomAnchor.constraint(equalTo: superview.bottomAnchor),
      self.leadingAnchor.constraint(equalTo: superview.leadingAnchor),
      self.trailingAnchor.constraint(equalTo: superview.trailingAnchor)
    ])
  }
}

たとえば、カスタムUIViewで、次のように使用できます。

let myView = UIView()
myView.backgroundColor = UIColor.red

self.addSubview(myView)
myView.bindFrameToSuperviewBounds()
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.