code

자동 레이아웃을 프로그래밍 방식으로 사용하여 수퍼뷰와 동일한 너비 및 높이?

starcafe 2023. 9. 25. 22:51
반응형

자동 레이아웃을 프로그래밍 방식으로 사용하여 수퍼뷰와 동일한 너비 및 높이?

인터넷에서 많은 토막글을 찾았지만 여전히 문제에 대한 답을 찾을 수 없습니다.내 질문은 스크롤뷰(SV)가 있는데 사용자가 장치 버튼을 회전할 때 장치 버튼이 동일한 프레임의 스크롤뷰(SV)를 갖도록 수퍼뷰의 너비와 높이가 동일한 스크롤뷰(SV) 내부 버튼을 프로그래밍 방식으로 추가하고 싶습니다. NSLayout/NSLayout 제약을 어떻게 합니까?감사해요.

누군가가 Swift 솔루션을 찾고 있다면, 저는 Swift 확장자를 만들어 서브뷰 프레임을 해당 수퍼뷰 경계에 묶을 때마다 도움이 될 것입니다.

스위프트 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]))
    }
}

스위프트 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()

이것이 가장 효율적인 방법인지는 모르겠지만, 효과는 있습니다.

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];

이 링크를 통해 지침을 준수할 수 있습니다. http://www.raywenderlich.com/20881/beginning-auto-layout-part-1-of-2

편집:

다음 코드 스니펫을 사용합니다. 여기서 subview는 당신의 subview입니다.

[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)]];

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

IMT2000 3GPP - 접근방식 #1: UIView 확장을 통한

여기 Swift 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()

위 방법은 이미핸디통합되어 있습니다.UIKit 프레임워크는 프로젝트에 보다 편리한 UI 도우미를 추가합니다.


접근 #2: 프레임워크 사용

프로젝트에서 프로그래밍 제약 조건을 많이 사용하는 경우 SnapKit을 확인하는 것이 좋습니다.이를 통해 제약 조건을 사용하는 작업이 훨씬 쉽고 오류가 발생하기 쉽습니다.

설치 지침에 따라 SnapKit을 프로젝트에 포함합니다.그런 다음 Swift 파일 맨 위에 가져옵니다.

import SnapKit

이제 이 작업만으로 동일한 작업을 수행할 수 있습니다.

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

스위프트 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]))
    }

}

스위프트 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])

다른 답변들 중에서 가장 좋은 요소를 꼽았습니다.

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()

PureLayout 라이브러리는 서드파티 라이브러리를 포함하는 것에 반대하지 않는 사람들을 위한 보충적인 답변으로서, 이를 수행할 수 있는 방법을 제공합니다.라이브러리를 설치하면 다음과 같이 간단합니다.

myView.autoPinEdgesToSuperviewEdges()

취향에 따라서도 비슷한 기능을 제공할 수 있는 다른 도서관들이 있습니다.메이슨리, 지도 제작.

@Dsche의 솔루션에 대한 후속 조치로 swift 3.0 구문이 있습니다. (참고: 이 솔루션은 솔루션이 아니며 Swift 3.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]))
}

저는 슈퍼뷰를 완전히 취재해야 했습니다.다른 사람들은 방향을 바꿀 때는 그러지 않을 겁니다.그래서 저는 임의의 크기의 곱셈기 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),
            ])
    }
}

언급URL : https://stackoverflow.com/questions/18756640/width-and-height-equal-to-its-superview-using-autolayout-programmatically

반응형