Language/Swift

[Swift] set size and position for view(CGRect, AutoLayout)

jaewpark 2022. 12. 1. 14:33

프로젝트를 하다보니 버튼, 이미지뷰 등을  CGRect로 배치를 하였으나 하나 하나 설정을 해줘야 되는 번거로움과 업데이트가 너무 힘들어서 다른 방법을 찾다보니 AutoLayout을 알게 되었고 코드를 수정을 하려고 한다.

 

CGRect (참고)

: A structure that contains the location and dimensions of a rectangle.

CGRect(x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat)
var imageButton: UIButton = {
    var button = UIButton(type: .custom)
    button.tintColor = .black
    button.frame = CGRect(x: 90, y: 110, width: 70, height: 70)
    return button
}()

x, y를 통해서 위치를 정하고 width, height를 통해서 크기를 정합니다.

 

장점

  • 세밀하게 위치를 조정할 수 있습니다

단점

  • 모든 프레임에 각각 입력을 해야합니다
  • 변경사항이 있을 때 업데이트가 어렵습니다

 

위와 같이 코드로 사용을 하였으나 단점을 직접 느끼다, 새로운 방법을 찾게 되었고 아래와 같은 AutoLayout을 찾아보았습니다.

 

AutoLayout (참고)

: Auto Layout은 뷰 계층 구조에 있는 모든 뷰의 크기와 위치를 해당 뷰에 적용된 제약 조건을 기반으로 동적으로 계산합니다. 제약 기반 접근 방식을 통해 내부 및 외부 변경 모두에 동적으로 응답하는 사용자 인터페이스를 구축할 수 있습니다.

 

출처 : 애플 공식문서

override func viewDidLoad() {
    super.viewDidLoad()

    let redView = UIView()
    redView.backgroundColor = .systemRed
    redView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(redView)

    redView.widthAnchor.constraint(equalToConstant: 100).isActive = true
    redView.heightAnchor.constraint(equalToConstant: 100).isActive = true
    redView.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
    redView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
}

위 코드를 아래와 같이 바꿀 수도 있습니다.

override func viewDidLoad() {
        super.viewDidLoad()
        
        let redView = UIView()
        redView.backgroundColor = .systemRed
        redView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(redView)
        
        NSLayoutConstraint.activate([
            redView.widthAnchor.constraint(equalToConstant: 100),
            redView.topAnchor.constraint(equalTo: view.topAnchor, constant: 100),
            redView.heightAnchor.constraint(equalTo: redView.widthAnchor, multiplier: 1),
            redView.centerXAnchor.constraint(equalTo: view.centerXAnchor)
        ])
    }

 


Safe Area

콘텐츠가 상태바, 네비게이션바, 툴바 등을 가리는 것을 방지하는 영역입니다.

출처: https://developer.apple.com/documentation/uikit/uiview/positioning_content_relative_to_the_safe_area



 

Constraint

뷰 스스로 또는 다른 뷰의 관계를 속성을 통하여 정의합니다.



출처 : https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/ProgrammaticallyCreatingConstraints.html

 

제약 우선도 (Constraint Priorities)

오토레이아웃은 제약 우선적으로 레이아웃에 적용되며 같은 속성의 다른 제약과 경합이 된다면 낮은 제약은 무시됩니다.

  1. 콘텐츠 허깅 우선도(Content hugging priority) : 콘텐츠 고유 사이즈보다 뷰가 커지지 않도록 제한합니다. 다른 제약사항보다 우선도가 높으면 뷰가 콘텐츠 사이즈보다 커지지 않습니다.
  2. 콘텐츠 축소 방지 우선도(Content compression resistance priority) : 콘텐츠 고유 사이즈보다 뷰가 작아지지 않도록 제한합니다. 다른 제약사항보다 우선도가 높으면 뷰가 콘텐츠 사이즈보다 작아지지 않습니다.

앵커 (Anchor) - 참고

오토레이아웃을 코딩으로 구현하여 제약을 만들기 위해서 사용합니다.

Layout Anchor는 위에 언급되었던 것과 같이 실행을 하면 됩니다.

 

var leftAnchor: NSLayoutXAxisAnchor { get }

: view 프레임의 왼쪽 가장자리로 제약 조건을 만듭니다.

var topAnchor: NSLayoutYAxisAnchor { get }

: view 프레임의 위쪽 가장자리로 제약 조건을 만듭니다.

var rightAnchor: NSLayoutXAxisAnchor { get }

: view 프레임의 오른쪽 가장자리로 제약 조건을 만듭니다.

var bottomAnchor: NSLayoutYAxisAnchor { get }

: view 프레임의 아래쪽 가장자리로 제약 조건을 만듭니다.

var centerXAnchor: NSLayoutXAxisAnchor { get }

: view 프레임의 가로 중심으로 제약 조건을 만듭니다.

var centerYAnchor: NSLayoutYAxisAnchor { get }

: view 프레임의 수직 중심으로 제약 조건을 만듭니다.

var heightAnchor: NSLayoutDimension { get }

: view 프레임의 높이를 나타내는 Layout Anchor입니다.

var widthAnchor: NSLayoutDimension { get }

: view 프레임의 너비를 나타내는 Layout Anchor입니다.

var leadingAnchor: NSLayoutXAxisAnchor { get }

: view 프레임의 앞 가장자리를 나타내는 Layout Anchor입니다.

var trailingAnchor: NSLayoutXAxisAnchor { get }

: view 프레임의 후행 가장자리를 나타내는 Layout Anchor입니다.

leading 과 left 그리고 trailing 과 right 의 차이는 글을 읽는 순서가 왼쪽이라서 다른 점이 없어보이겠지만
leading 은 텍스트의 시작점이며, trailing 은 텍스트의 끝점입니다.
나라별로 읽는 순서가 다르기에 LTR(Left To Right) 과 RTL(Right To Left) 원활히 지원을 하기 위해서
left, right 보다는 leading, trailing을 사용하는 것을 권장합니다.
var firstBaselineAnchor: NSLayoutYAxisAnchor { get }

: view 에서 텍스트의 맨 위 줄에 대한 기준선을 나타내는 Layout Anchor입니다.

var lastBaselineAnchor: NSLayoutYAxisAnchor { get }

: view 에서 텍스트의 맨 아래 줄에 대한 기준선을 나타내는 Layout Anchor입니다.

 

 

출처 : https://milyo-codingstories.tistory.com/51

newLabel  = UILabel()
newLabel.text = "new"
newLabel.leadingAnchor.constraint(equalTo: baseLabel.trailingAnchor,constant: 8).isActive = true
newLabel.topAnchor.constraint(equalTo: baseLabel.firstBaselineAnchor).isActive = true