본문 바로가기
iOS

[iOS] Code로 AutoLayout 다루기

by teamnova 2022. 1. 16.
728x90

오늘은 코드로 오토레이아웃을 구현해보겠습니다.

 

Auto Layout 이란?

Auto Layout dynamically calculates the size and position of all the views in your view hierarchy, based on constraints placed on those views.

 

한마디로 뷰의 크기와 위치를 constraints에 의해서 동적으로 계산해주는 레이아웃 입니다.

 

 

기존의 Frame-Base Layout 과 비교해 볼까요? 

 

Auto Layout의 가장 큰 장점은 여러 해상도를 유연하게 지원할 수 있다는 것입니다.
왼쪽과 같이 Frame-Base Layout으로 뷰를 그리면 의도된 해당도를 지원하는 단말기에서는 정상적으로 보이겠지만, 더 작은 해상도라던지, 더 큰 해상도에서 보게되면 여백이 많이 줄어들거나, 반대로 여백이 많이 생길 수 있습니다.
Auto Layout의 경우에는 왼쪽, 오른쪽에 제약사항을 걸어두었으니 해상도가 작은 단말기든, 높은 단말기든 상관없이 부모 뷰로부터 왼쪽에서 20, 오른쪽에서 20만큼 떨어져서 뷰가 그려집니다.

 

 

코드로 오토레이아웃을 구현하는 방법은 3가지가 있습니다. 

  • 앵커(Anchor)를 통해서 구현
  • NSLayoutConstraint 인스턴스로 구현
  • Visual Format Language 를 통해 구현

 

 

뷰를 그려줄때 다음의 순서를 지켜줘야 합니다.

  1. UI 요소들 정의
  2. addSubView
  3. bind constraints

 

 

UI요소들 정의 

class AutoLayoutView: UIView {
  
  let titleLabel: UILabel = {
    let label = UILabel()
    
    label.text = "AutoLayout 만들기👋"
    label.textColor = .black
    label.font = .systemFont(ofSize: 24)
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
  }()
  
  let descriptionLabel: UILabel = {
    let label = UILabel()
    
    label.text = "설명이 여기에 들어갈껀데용?"
    label.textColor = .gray
    label.font = .systemFont(ofSize: 15)
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
  }()
  
  ...
}

여기서 매 요소마다 설정해주는 아주 긴 이름이 보이네요 

translatesAutoresizingMaskIntoConstraints 는 뭘까요? 

 

AutoResizing 이란 개념을 알고 넘어가야 하지만 이건 다른 포스팅에서 다루겠습니다. 

 

쉽게말해 우리는 동적으로 뷰의 위치와 크기를 결정할 것이기 때문에 false로 설정해 주는 겁니다. 

 

 

 

addSubView / bind constraints

import UIKit

class AutoLayoutView: UIView {

  ...
  
  override init(frame: CGRect) {
    super.init(frame: frame)
    
    // Setup
    self.backgroundColor = .white
    self.addSubview(titleLabel)
    self.addSubview(descriptionLabel)
    
    
    // Bind constraints
    self.titleLabel.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 24).isActive = true
    self.titleLabel.topAnchor.constraint(equalTo: self.safeAreaLayoutGuide.topAnchor, constant: 24).isActive = true
    
    self.descriptionLabel.leftAnchor.constraint(equalTo: self.titleLabel.leftAnchor).isActive = true
    self.descriptionLabel.topAnchor.constraint(equalTo: self.titleLabel.bottomAnchor, constant: 5).isActive = true
  }
  
  required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
}

 

titleLabel의 left에 대한 제약사항을 먼저 만들어줍니다.

self.titleLabel.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 24).isActive = true

 

 titleLabel의 top은 상단 safeAreaLayout으로부터 24만큼 떨어져야하므로 위와같이 설정해줍니다.

self.titleLabel.topAnchor.constraint(equalTo: self.safeAreaLayoutGuide.topAnchor, constant: 24).isActive = true

 

이렇게 뷰 클래스를 만들어 놓고 ViewController에서 view만 방금 만든 뷰 클래스로 설정해주면 되겠죠?

import UIKit

class ViewController: UIViewController {
  
  private lazy var autoLayoutView = AutoLayoutView(frame: self.view.frame)
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    self.view = autoLayoutView
  }
}