[TIL] 21.03.31.(Wed)

Ryan (Geonhee) Son·2021년 4월 4일
0

활동 내용

  • Auto Layout 독학: 야곰닷넷 - 오토레이아웃 정복하기
    • ~ Debugging Auto Layout

학습 내용

활동학습 전에 다 보겠다고 중간부터 기록을 안 했는데 이후에 반드시 하겠습니다 (임시글 형태로 계속 작성 중).

Understanding Auto Layout

  • Auto Layout Guide

    Auto Layout은 크기와 위치를 constraints를 기반으로 계산합니다.
  • constraint-based approach 동적으로 view가 배치되고 사이즈가 조정됩니다.

View가 변화할 수 있는 요인

외부적 요인 (External Changes)

  • mac을 사용하고 있다면, mac에서 사용자가 윈도우 크기를 조정한다면 안에 배치되어있던 뷰들의 사이즈가 동적으로 조정되고 요소들의 위치가 이동됩니다.
  • split view로 진입
  • 기기의 방향(가로/세로) 전환
  • Call과 recording bar가 나타나고 사라짐 (일반적인 status bar 보다 크기가 큼)
  • 다른 size classes를 지원하고자 할 때 (HIG 참고)
  • 다른 screen sizes를 지원하고자 할 때 (HIG 참고)

내부적 요인 (Internal Changes)

  • 앱 변화에 따른 컨텐츠 변화 (예를 들어, 사용자의 버튼 탭으로 인한 요소들의 변화)
  • 앱이 internationalization을 지원할 경우
  • 앱이 Dynamic Type을 지원할 경우 (HIG 참고)

이렇듯 외부적, 내부적 요인으로 인해 뷰가 항상 유동적으로 변할 수 있기 때문에 Auto Layout을 사용하여 UI를 구성하면 변동에 유연하게 대응할 수 있습니다.

Auto Layout vs Frame-Based Layout


위의 그림과 같이 기존에 이용하던 Frame-Based Layout을 사용하면 절대적인 크기를 가지기에 여러가지 기기의 화면 크기에 대응하기 어렵습니다. 반면에, 아래 그림과 같이 화면에 상대적으로 컨텐츠를 조정하게 한다면 뷰의 크기에 따라 유연하게 대응할 수 있을 것입니다. 이 개념이 Auto Layout의 핵심 개념입니다.

Anatomy of a Constraint

Auto Layout제약 (Constraint)에 대해 알아보겠습니다.

Anatomy of a Constraint(1)

Attributes

이전 포스팅에서 말씀드렸듯이 Auto Layout의 핵심은 제약 (Constraint)입니다.

위는 Apple이 제시한 그림입니다. 그림에서 Auto Layout은 파란색과 빨간색 뷰 아래에 나타낸 것처럼 하나의 수식으로 나타낼 수 있다고 표현하고 있습니다. 파란색 뷰와 빨간색 뷰의 상대적인 위치를 나타내는 것이죠. 수식을 읽어보면 빨간색 뷰는 파란색 뷰와 8 포인트만큼 떨어져 있다고 표현하고 있네요. 포인트는 HIG에 개념이 자세히 나와있으니 읽어보시면 더 도움이 될 것입니다 (픽셀과 다른 개념입니다). 수식을 좀 더 자세히 읽어볼까요?

RedView.Leading = 1.0 * BlueView.Trailing + 8.0
// 빨간색뷰(RedView)의 머리(Leading)는 파란색 뷰(BlueView)의 꼬리(Trailing)로부터 8 포인트 떨어져있다.

수식의 =은 그림에 기재된 바와 같이 둘 간의 관계 (relationship)을 나타냅니다. = 이외의 관계도 있지만 앞으로 차근차근 마주하게 될 것입니다.


위는 Attributes를 나타내는 그림입니다. Top, Left or Leading, Right or Trailing, Bottom, Width, Height, Center X, Center Y, 그리고 Baseline이 있다고 하네요. 여기에서 좌우측을 나타내는 키워드로 LeadingTrailing을 병기하고 있는데, 이는 글이 시작하는 방향을 의미합니다. 미국의 영어가 한글과 같이 좌측에서 우측으로 작성되기 때문에 이러한 표현을 사용합니다. 반면에 Apple이 우측에서 좌측으로 글을 작성하는 언어를 가진 나라의 회사였다고 한다면 반대가 되었을 수 있겠네요 😀. LeftRight라는 표현보다는 LeadingTrailing이라는 표현을 사용하기를 권장합니다. Not An Attribute 요소는 다음 시간에 알아보도록 하겠습니다.

Note

Baseline은 글자의 밑 바닥 부분을 나타내는 키워드입니다. 뷰 안에 글자가 들어가는 요소들에 활용할 수 있습니다.

Anatomy of a Constraint(2)

Sample Equations

지난 시간에 살펴본 Attributes 그림을 보시겠습니다.

Attributes는 아래와 같이 크게 두 가지로 분류할 수 있습니다.
1. 크기를 나타내기 위한 Attributes (Width, Height)
2. 위치를 나타내기 위한 Attributes (위 두 가지와 Not An Attribute를 제외한 모든 Attributes)


애플 또한 문서에서 Size AttributesLocation Attributes가 있다고 소개하며 다섯가지 적용 규칙을 알려줍니다.

  • Size attributelocation attribute로 제약을 가할 수 없다 (둘을 섞어서 사용할 수 없다).
  • Location attributes에는 상수를 할당할 수 없다.
  • Location attributes에는 1 이외의 값을 가지는 nonidentity multiplier를 사용할 수 없다.
  • Location attributes의 경우, Vertical attributeshorizontal attributes로 제약을 가할 수 없다 (둘을 섞어서 사용할 수 없다)
  • Location attributes의 경우, Leading 또는 Trailiing attributesLeft 또는 Right attributes로 제약을 가할 수 없다.

그러면 애플이 제시한 예시 수식들을 함께 보시겠습니다.

// Setting a constant height
View.height = 0.0 * NotAnAttribute + 40.0
 
// Setting a fixed distance between two buttons
Button_2.leading = 1.0 * Button_1.trailing + 8.0
 
// Aligning the leading edge of two buttons
Button_1.leading = 1.0 * Button_2.leading + 0.0
 
// Give two buttons the same width
Button_1.width = 1.0 * Button_2.width + 0.0
 
// Center a view in its superview
View.centerX = 1.0 * Superview.centerX + 0.0
View.centerY = 1.0 * Superview.centerY + 0.0
 
// Give a view a constant aspect ratio
View.height = 2.0 * View.width + 0.0


지금까지 살펴본 바와 같이 =의 의미는 기존에 프로그래밍 개념에서 사용하던 할당한다 (assign)의 의미가 아닌 수학적 같음 (equality)를 의미합니다. 이는 수식의 좌변과 우변의 값이 다를 때 에러가 발생한다는 뜻입니다. Storyboard에서 빨간색 줄이 보이거나, UI가 의도와 다르게 위치하거나 동작하고, 심하면 크래시가 발생하는 등의 현상이 발생할 수 있습니다. 아래 수식들은 위에서 제시한 코드와 동일하게 작동하는 코드로, = 기호가 수학적으로 같음을 의미하는 것을 보여주는 사례입니다.

// Setting a fixed distance between two buttons
Button_1.trailing = 1.0 * Button_2.leading - 8.0
 
// Aligning the leading edge of two buttons
Button_2.leading = 1.0 * Button_1.leading + 0.0
 
// Give two buttons the same width
Button_2.width = 1.0 * Button.width + 0.0
 
// Center a view in its superview
Superview.centerX = 1.0 * View.centerX + 0.0
Superview.centerY = 1.0 * View.centerY + 0.0
 
// Give a view a constant aspect ratio
View.width = 0.5 * View.height + 0.0

Anatomy of a Constraint(3)

Creating Nonambiguous Layouts

이번 주제는 '모호하지 않은 Layout을 만들기 (명확한 Layout 만들기)'라는 주제입니다. Auto Layout을 사용하는 목표는 constraintview에게 제시해서 view가 스스로 자신의 크기와 있어야 할 곳을 찾아가게 하기 위함입니다. 이는 바꾸어 말하면 하나의 요소라도 부족하다면 view가 의도한대로 동작하지 않을 수 있다는 뜻입니다. 컴퓨터는 사람이 아니기에 정확한 주문을 하지 않으면 의도한대로 동작하지 않을 가능성이 큽니다. 아래 그림을 보시겠습니다.


먼저, 만약 가로 방향에 제약을 주는 상황을 가정해보겠습니다. 위의 세 가지 사례 중 가장 명확하게 지침을 주고 있는 그림은 몇 번째 그림일까요? 결론적으로 모두 적절하게 주문하고 있습니다. 첫 번째 사례는 superView로 부터 떨어진 위치와 view의 너비를 제시하였으니 view의 시작점과 끝점을 도출할 수 있습니다. 두번째 사례는 view의 좌우측 공간이 superView로부터 떨어진 거리를 나타내므로 시작점과 끝점을 알 수 있습니다. 세 번째 사례는 viewsuperView로부터 떨어진 거리와 superView의 x축 중심이 일치한다는 제약을 주어 시작점과 끝점을 view의 위치와 크기를 명확하게 전달하였습니다. 결국 시작 위치끝 위치 또는 너비만 제대로 전달해주면 된다는 것을 알 수 있습니다.

Anatomy of a Constraint(4)

Variety Solutions

이번에는 실질적인 예제를 통해 살펴보겠습니다. 아래 그림을 보면 세로 방향 (portrait)일 때와 가로 방향 (landscape)일 때의 예시가 나와 있습니다.

위와 같이 view를 구성하려면 Auto Layout을 어떻게 적용하면 될까요? 실습을 통해 알아봅시다.

아래 그림은 직접 Storyboard에서 2 개의 view 요소들을 화면에 올리고 좌측 view 요소의 위아래 위치에 제약을 걸어준 모습입니다. 화면에서의 거리를 나타내는 파란색 선과 view의 위아래 선이 짙은 파란색으로 표현되고 있습니다. 이 짙은 파란색 실선은 view가 어느 위치에 어떤 크기로 존재해야할지 명확히 알았다는 뜻입니다.

Tip

Auto Layout의 contraint를 적용하기 전에 의도한 대략적인 위치와 크기를 잡아두면 편하게 작업할 수 있습니다.

이번에는 잘못된 예시를 가져왔습니다. 가로 방향으로 constraint를 적용하는 과정에서 각 view의 좌우측에 모두 20 포인트만큼 떨어졌으면 좋겠다고 주문했습니다. 이렇게 잘못된 주문을 하면 view들이 빨간색 선을 나타내며 아직 자리를 찾아가지 못했다고 표현합니다.

이 경우 위의 화면과 같이 좌측 상단의 View Controller Scene에 자그만한 붉은 화살표 버튼이 생깁니다.

이 화살표를 눌러보면 Auto Layout의 잘못된 사항들과 부족한 사항들을 알려줍니다.

지금 살펴보면 'x의 위치 또는 너비를 모르겠다'라고 표현하는데 생각해보면 맞는 말입니다. view를 의도적으로 비슷한 너비가 되도록 그렸지만, 고정된 크기가 아니기에 왼쪽 view 크기와 오른쪽 view 크기를 조정한다면 얼마든지 현재 부여한 제약을 만족하는 경우를 수도없이 찾아낼 수 있기 때문이죠. 만약, 두 view의 크기가 같다고 의도한 것이라면, 해당 제약을 두 view에 적용해주어야 합니다.

그러면 위치와 크기가 모두 결정되었기에 정상적으로 두 view가 의도한 자리에 위치했음을 확인할 수 있습니다.

하지만 두 view 사이의 가로 제약이 같은 곳에 두 개나 필요할까요? 아닙니다. 두 view 사이에 constraint가 존재한다면 이미 두 view는 서로를 알기 때문에 중복되는 constraint는 필요 없습니다.

content compression resistance: 줄어들지 않으려고 버티는 힘
content hugging: 늘어나지 않으려고 버티는 힘

profile
합리적인 해법 찾기를 좋아합니다.

0개의 댓글