Auto Layout
독학: 야곰닷넷 - 오토레이아웃 정복하기활동학습 전에 다 보겠다고 중간부터 기록을 안 했는데 이후에 반드시 하겠습니다 (임시글 형태로 계속 작성 중).
Auto Layout
은 크기와 위치를 constraints
를 기반으로 계산합니다.constraint-based approach
동적으로 view가 배치되고 사이즈가 조정됩니다.internationalization
을 지원할 경우Dynamic Type
을 지원할 경우 (HIG 참고)이렇듯 외부적, 내부적 요인으로 인해 뷰가 항상 유동적으로 변할 수 있기 때문에 Auto Layout
을 사용하여 UI를 구성하면 변동에 유연하게 대응할 수 있습니다.
Auto Layout
vs Frame-Based Layout
위의 그림과 같이 기존에 이용하던 Frame-Based Layout
을 사용하면 절대적인 크기를 가지기에 여러가지 기기의 화면 크기에 대응하기 어렵습니다. 반면에, 아래 그림과 같이 화면에 상대적으로 컨텐츠를 조정하게 한다면 뷰의 크기에 따라 유연하게 대응할 수 있을 것입니다. 이 개념이 Auto Layout
의 핵심 개념입니다.
Auto Layout
의 제약 (Constraint)
에 대해 알아보겠습니다.
이전 포스팅에서 말씀드렸듯이 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
이 있다고 하네요. 여기에서 좌우측을 나타내는 키워드로 Leading
과 Trailing
을 병기하고 있는데, 이는 글이 시작하는 방향을 의미합니다. 미국의 영어가 한글과 같이 좌측에서 우측으로 작성되기 때문에 이러한 표현을 사용합니다. 반면에 Apple이 우측에서 좌측으로 글을 작성하는 언어를 가진 나라의 회사였다고 한다면 반대가 되었을 수 있겠네요 😀. Left
와 Right
라는 표현보다는 Leading
과 Trailing
이라는 표현을 사용하기를 권장합니다. Not An Attribute
요소는 다음 시간에 알아보도록 하겠습니다.
Note
Baseline은 글자의 밑 바닥 부분을 나타내는 키워드입니다. 뷰 안에 글자가 들어가는 요소들에 활용할 수 있습니다.
지난 시간에 살펴본 Attributes
그림을 보시겠습니다.
Attributes
는 아래와 같이 크게 두 가지로 분류할 수 있습니다.
1. 크기를 나타내기 위한 Attributes
(Width
, Height
)
2. 위치를 나타내기 위한 Attributes
(위 두 가지와 Not An Attribute
를 제외한 모든 Attributes
)
애플 또한 문서에서 Size Attributes
와 Location Attributes
가 있다고 소개하며 다섯가지 적용 규칙을 알려줍니다.
Size attribute
를 location attribute
로 제약을 가할 수 없다 (둘을 섞어서 사용할 수 없다).Location attributes
에는 상수를 할당할 수 없다.Location attributes
에는 1 이외의 값을 가지는 nonidentity multiplier
를 사용할 수 없다.Location attributes
의 경우, Vertical attributes
를 horizontal attributes
로 제약을 가할 수 없다 (둘을 섞어서 사용할 수 없다)Location attributes
의 경우, Leading
또는 Trailiing attributes
를 Left
또는 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
이번 주제는 '모호하지 않은 Layout
을 만들기 (명확한 Layout
만들기)'라는 주제입니다. Auto Layout
을 사용하는 목표는 constraint
를 view
에게 제시해서 view
가 스스로 자신의 크기와 있어야 할 곳을 찾아가게 하기 위함입니다. 이는 바꾸어 말하면 하나의 요소라도 부족하다면 view
가 의도한대로 동작하지 않을 수 있다는 뜻입니다. 컴퓨터는 사람이 아니기에 정확한 주문을 하지 않으면 의도한대로 동작하지 않을 가능성이 큽니다. 아래 그림을 보시겠습니다.
먼저, 만약 가로 방향에 제약을 주는 상황을 가정해보겠습니다. 위의 세 가지 사례 중 가장 명확하게 지침을 주고 있는 그림은 몇 번째 그림일까요? 결론적으로 모두 적절하게 주문하고 있습니다. 첫 번째 사례는 superView
로 부터 떨어진 위치와 view
의 너비를 제시하였으니 view
의 시작점과 끝점을 도출할 수 있습니다. 두번째 사례는 view
의 좌우측 공간이 superView
로부터 떨어진 거리를 나타내므로 시작점과 끝점을 알 수 있습니다. 세 번째 사례는 view
가 superView
로부터 떨어진 거리와 superView
의 x축 중심이 일치한다는 제약을 주어 시작점과 끝점을 view
의 위치와 크기를 명확하게 전달하였습니다. 결국 시작 위치
와 끝 위치
또는 너비
만 제대로 전달해주면 된다는 것을 알 수 있습니다.
이번에는 실질적인 예제를 통해 살펴보겠습니다. 아래 그림을 보면 세로 방향 (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: 늘어나지 않으려고 버티는 힘