iOS AutoLayout

YEOMI·2023년 10월 31일

Swfit - Coding Bottle

목록 보기
8/13

AutoLayout

뷰에 적용된 제약 조건(constraints)을 기반으로 뷰 계층 구조에 있는 모든 뷰의 레이아웃을 자동으로 계산하여 그려줍니다.

다양한 제약 조건(leading, trailing, top, bottom, width, height 등)을 활용하여 뷰 간의 상대적인 위치와 크기를 정의합니다.

Interface Builder를 사용하여 시각적으로 제약 조건을 설정할 수 있고, 코드로도 제약 조건을 프로그래밍적으로 설정할 수 있습니다.

제약 조건의 우선순위 (Priority):

복합 제약 조건 (Compound Constraints):

핵심 !

  • 뷰의 x,y 위치
  • 뷰의 가로 세로 크기
    이 4가지의 값을 구하는 시스템인 것입니다.

조건을 어떻게 주느냐에 따라서 값을 계산하는데, 수식으로 나타내 보면

y = ax + b

x,y는 서로 다른 뷰의 속성
a,b는 개발자가 지정하는 임의의 수

iOS가 모든 뷰의 4가지 값(= x,y의 위치/ 가로,세로 크기)를 구할 수 있도록,
개발자는 뷰와 뷰 사이의 상대적인 관계를 표현한 방정식(=조건)을 여러개 만들어서 전달합니다.

뷰의 속성

//조건 예시
// 높이를 40포인트로 지정한다.
View.height = 0.0 * NotAnAttribute + 40.0

// 두 버튼 사이의 간격을 8포인트 띄운다.
Button2.leading = 1.0 * Button1.trailing + 8.0

// 두 버튼의 왼쪽을 정렬한다.
Button1.leading = 1.0 * Button2.leading + 0.0

// 두 버튼의 너비를 똑같이 만든다.
Button1.width = 1.0 * Button2.width + 0.0

// 상위 뷰와 가운데 정렬을 한다.
View.centerX = 1.0 * Superview.centerX + 0.0

// 높이를 너비의 두배로 만든다.
View.height = 2.0 * View.width + 0.0

X축 기준으로 Leading, Trailing, Width, Center X 이렇게 4가지 속성이 있습니다.
이 중 2개가 정해져야 한다. (Y축도 동일)

테두리 속성 1개 (Leading or Trailing) + 테두리 속성 1개 (Leading or Trailing)
테두리 속성 1개 (Leading or Trailing) + 너비 속성 (Width)
테두리 속성 1개 (Leading or Trailing) + 중심축 속성 (Center X)
너비 속성 (Width) + 중심축 속성 (Center X)

// WriteViewController.swift 중 AutoLayout 부분

    // 1. UI 요소들의 위치와 크기를 설정하는 메서드
    private func setupUIConstraints() {
        titleField.translatesAutoresizingMaskIntoConstraints = false
        imageView.translatesAutoresizingMaskIntoConstraints = false
        hashtagField.translatesAutoresizingMaskIntoConstraints = false
        
        // 2.각 UI 요소들의 위치와 크기를 제약 조건을 통해 정의
        NSLayoutConstraint.activate([
            // titleField의 상단을 tableView의 safeAreaLayoutGuide의 상단에서 20 포인트 아래에 배치합니다.
            titleField.topAnchor.constraint(equalTo: tableView.safeAreaLayoutGuide.topAnchor, constant: 20),
            
            // titleField의 왼쪽을 view의 layoutMarginsGuide의 왼쪽에 정렬합니다.
            titleField.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor),
            
            //titleField의 오른쪽을 view의 layoutMarginsGuide의 오른쪽에 정렬합니다.
            titleField.trailingAnchor.constraint(equalTo: view.layoutMarginsGuide.trailingAnchor),
                 
            //titleField의 높이를 50 포인트로 고정합니다.
             titleField.heightAnchor.constraint(equalToConstant: 50),
             
            //imageView는 titleField 아래에 위치하고, 가로 너비와 세로 높이를 같게 설정하여 이미지를 정사각형 모양으로 유지합니다.
            imageView.topAnchor.constraint(equalTo: titleField.bottomAnchor, constant: 20),
            imageView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor),
            imageView.trailingAnchor.constraint(equalTo: view.layoutMarginsGuide.trailingAnchor),
            imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor), // 이미지 높이와 너비 동일
            
            //imagePickerButton은 imageView 아래 중앙에 배치됩니다.
            imagePickerButton.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 20),
            imagePickerButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            
            //hashtagField은 imagePickerButton 아래에 위치하고, 높이를 50 포인트로 고정합니다.
            hashtagField.topAnchor.constraint(equalTo: imagePickerButton.bottomAnchor, constant: 10),
            hashtagField.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor),
            hashtagField.trailingAnchor.constraint(equalTo: view.layoutMarginsGuide.trailingAnchor),
            hashtagField.heightAnchor.constraint(equalToConstant: 50)
        ])
    }

코드 추가 설명

  1. titleField, imageView, hashtagField을 비활성화:
    각 UI 요소는 translatesAutoresizingMaskIntoConstraints를 false로 설정하여 기존의 자동으로 생성된 제약 조건을 해제합니다. 이렇게 하면 새로운 제약 조건을 수동으로 추가할 수 있게 됩니다.

  2. NSLayoutConstraint.activate를 사용하여 여러 개의 제약 조건을 한 번에 활성화:
    activate 메서드를 사용하여 여러 NSLayoutConstraint를 한 번에 활성화합니다. 이를 통해 여러 제약 조건을 간결하게 관리할 수 있습니다.

StackView

2015년 iOS 9에서 처음으로 등장, Stack View는 오토레이아웃을 편리하게 사용하도록 도와주기 위해 만들어졌습니다.

스택 뷰는 자동 레이아웃을 사용하여 정렬된 뷰의 위치와 크기를 조정합니다. 스택 뷰는 첫 번째와 마지막으로 정렬된 뷰를 스택 축을 따라 해당 가장자리에 정렬합니다. 수평 스택에서 이는 첫 번째로 정렬된 뷰의 앞쪽 가장자리가 스택의 앞쪽 가장자리에 고정되고 마지막으로 정렬된 뷰의 뒤쪽 가장자리가 스택의 뒤쪽 가장자리에 고정됨을 의미합니다. 수직 스택에서는 위쪽 및 아래쪽 가장자리가 각각 스택의 위쪽 및 아래쪽 가장자리에 고정됩니다.

-자동 레이아웃 관리: Stack View는 자식 뷰들의 위치와 크기를 자동으로 관리합니다. 이는 복잡한 레이아웃을 구현할 때 필요한 수많은 제약 조건을 직접 추가하거나 관리할 필요가 없다는 것을 의미합니다.
-방향성: Stack View는 수직(vertical) 또는 수평(horizontal) 방향으로 자식 뷰들을 배치합니다. 이는 --stack view의 axis 속성을 통해 설정할 수 있습니다.

  • 배분 방식: Stack View는 공간을 어떻게 배분할지 결정하는 distribution 속성을 가지고 있습니다. 이 속성의 값에 따라 자식 뷰들이 동일한 크기를 가지거나, 동일한 공간을 차지하거나, 콘텐츠에 맞는 크기를 가지도록 할 수 있습니다.
  • 정렬 방식: Stack View는 자식 뷰들을 어떻게 정렬할지 결정하는 alignment 속성을 가지고 있습니다. 이 속성의 값에 따라 자식 뷰들이 stack view의 leading, center, trailing 등에 정렬되거나, stack view를 꽉 채우도록 설정할 수 있습니다.
  • 간격 설정: Stack View는 자식 뷰들 사이의 간격을 설정하는 spacing 속성을 가지고 있습니다. 이 속성을 사용하면 자식 뷰들 사이의 공간을 쉽게 조절할 수 있습니다.
  • 자동 적응: Stack View는 화면 크기나 방향이 변경될 때 자동으로 적응합니다. 예를 들어, iPhone에서 세로 모드에서 가로 모드로 변경될 때, Stack View는 자식 뷰들의 배치를 자동으로 조절하여 최적의 레이아웃을 유지합니다.
stackView.axis = .horizontal //스택 뷰의 방향을 수직 또는 수평으로 정의합니다.
stackView.distribution = .fillEqually //축을 따라 뷰의 레이아웃을 정의합니다.
stackView.alignment = .center //스택 뷰의 축에 수직인 뷰의 레이아웃을 정의합니다.
stackView.spacing = 10 //인접한 뷰 사이의 공간을 정의합니다.
//ReportView.swift StackView 사용 부분
override init(frame:CGRect) {
        super.init(frame:frame)

        // UIStackView를 생성
        let stackView = UIStackView()
        stackView.axis = .vertical // 수직 스택뷰로 설정 (버튼들이 위 아래로 쌓이게 됨)
        stackView.alignment = .center // 중앙 정렬
        stackView.spacing = 40 // 버튼 사이의 간격 설정
        
        self.backgroundColor = UIColor.white

        // 버튼들을 UIStackView에 추가
        stackView.addArrangedSubview(sbsButton)
        stackView.addArrangedSubview(kbsButton)
        stackView.addArrangedSubview(mbcButton)

        // UIStackView를 view에 추가
        addSubview(stackView)

        // UIStackView의 Auto Layout 제약 조건 설정 (가운데 정렬)
        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
        stackView.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
        stackView.widthAnchor.constraint(equalToConstant: 300).isActive = true // 원하는 너비로 설정
        stackView.heightAnchor.constraint(equalToConstant: 230).isActive = true // 원하는 높이로 설정
        

    }
//ReportviewController.swift AutoLayout 사용 부분
override func viewDidLoad() {
        super.viewDidLoad()
        

        // reportView를 화면에 추가하고 크기를 설정
        view.addSubview(reportView)
        reportView.translatesAutoresizingMaskIntoConstraints = false
        reportView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        reportView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        reportView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        reportView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        
 
        // textView를 화면에 추가하고 크기를 설정
        view.addSubview(textView)
        
        textView.translatesAutoresizingMaskIntoConstraints = false
        textView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        textView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20).isActive = true

ReportView는 StackView로 구현하고, TextView와 ReportViewController에서는 AutoLayout을 사용하여 정의하였습니다.

장점

  • 간편한 레이아웃 관리: Stack View는 자식 뷰의 위치와 크기를 자동으로 관리하기 때문에, 수동으로 제약 조건을 추가하거나 관리할 필요가 없습니다. 이는 복잡한 레이아웃을 구성하는 데 큰 도움이 됩니다.
  • 동적인 UI 조정: 화면 크기나 방향이 변경될 때, Stack View는 자식 뷰의 배치를 자동으로 조정합니다. 이는 다양한 장치 크기와 방향에 대응하는 UI를 만드는 데 유용합니다.
  • 간편한 뷰 추가 및 제거: Stack View에서 뷰를 추가하거나 제거하는 것은 매우 간단합니다. Stack View는 자동으로 레이아웃을 조정하여 새로운 뷰를 반영하거나 제거된 뷰를 적용합니다.
  • 중첩된 StackView를 생성해 복잡한 레이아웃을 구성하는 데에도 유용합니다.

단점

  • 복잡한 레이아웃 제한: Stack View는 선형적인 레이아웃만 지원하므로, 더 복잡한 레이아웃을 구성하려면 여러 Stack View를 중첩해야 합니다. 이 경우 레이아웃이 복잡해지고, 관리하기 어렵습니다.
  • 세세한 조절 불가능: Stack View는 자식 뷰의 위치와 크기를 자동으로 관리하기 때문에, 세세한 조절이 필요한 경우 제한적일 수 있습니다. 예를 들어, 특정 뷰만 다른 뷰와 다르게 배치하거나 크기를 조절하려면 추가적인 작업이 필요합니다.
    ->이럴 경우 AutoLayout을 직접 사용.
profile
뭐라도 좀 해라

0개의 댓글