deprecated/꼼꼼한 재은씨 시리즈

[iOS14] 오토 리사이징 + 오토 레이아웃 정리

lgvv 2021. 5. 26. 01:09

 iOS 디바이스별 크기에 따라 UI 대응방향

1. 화면 크기의 변화에 따라 가로, 세로 길이 유지한 채 외부 간격만 늘림

2. 화면 크기의 변화에 따라 가로, 세로 길이 변화시키면서 외부 간격은 유지

 - 아무것도 선택하지 않을 시, 간격 및 크기 고정

 

iOS 레이아웃 제어 기능 제공

1. 오토 리사이징 

 - [View] 메뉴 - [Inspectors] - [show size Inspector]

 - <option> + <command> + <5>

2. 오토 레이아웃

 

 

오토 리사이징

오토 리사이징 기본값 - 화면좌측 상단에 고정되어 있는 모습

설정 창 왼쪽을 보면은 사각형 두개가 중첩되어 있음

왼쪽 사각형 내부에 표시된 화살표와 간격 기호들은 선택된 객체와 상위뷰의 관계를 나타낸다.

사각형 바깥쪽은 객체를 포함하고 있는 상위 뷰를 의미하고,

사각형 안쪽은 선택된 객체를 의미한다.

 

사각형 내부에 있는 너비와 높이에는 간격이 표시되어 있는데 토글 형식으로 클릭으로 활성과 비활성을 설정할 수 있다.

사각형 바깥쪽에 있는 부분을 활성화 하면 화면의 크기와 관계없이 객체의 간격이 그대로 유지된다는 것이다.

 

내부 사각형에 표시된 가로와 세로는 의미가 다르다. 화면의 크기가 늘어날 때, 객체의 크기가 함께 늘어남을 의미한다. 따라서 화면 크기에 따라 객체의 크기가 자연스럽게 늘어가도록 하려면 외부 사각형에서의 적절한 간격 설정과 함께 내부의 너비와 높이 표시를 활성화해야 한다. 이처럼 오토 리사이징은 내부 사각형과 외부 사각형의 간격과 크기 설정을 조합하여 원하는 결과를 만들어 낼 수 있다.

 

설정창 오른쪽 미리 보기 영역에 있는 사각형 객체의 크기가 움직이면서 레이아웃이 어떤 식으로 변화할지를 보여준다. 이를 참고하면 레이아웃을 바로 이해할 수 있을 뿐만 아니라 우리가 원하는 레이아웃을 설정하기 위해 어느 부분의 간격을 활성화 또는 비활성화해야 할지 판단할 수 있다. 

 

뷰가 여럿일 때, 각자 뷰의 너비를 유지하기 위해 서로를 덮거나 간섭하는 현상이 생기면 안된다. 이 같은 요구조건을 만족하려면 다음과 같은 오토 리사이징 설정이 필요하다.

스토리보드(아이폰SE2) - 시뮬레이터(아이폰12)
빨간색 뷰
초록색 뷰

 

위의 그림을 보아 간격이 유지되는 것을 확인할 수 있다. 

다만 오토 리사이징의 한계가 존재하는데, 바로 회전 시 제대로 대응하지 못하는 문제인데, 심지어는 아예 원하는 형태를 보여주지 못하는 상태라고 할 수 있다.  --> 사진을 첨부하진 않으나 회전은 위의 예시로 직접 해보면 문제 발생함을 바로 알 수 있다. 

이에 따라 iOS는 더 강력하고 세밀하게 레이아웃을 제어하기 위해 새로운 기능을 도입했는데, 이것이 바로 오토 레이아웃이다.

 

 

오토 레이아웃

 

 오토 리사이징을 대체하기 위해 도입된 오토 레이아웃은 오토 리사이징만큼 직관적이지도, 사용하기 쉽지도 않다. 하지만 기능만큼은 매우 강력해서 오토 레이아웃을 이용하여 설정한 화면 인터페이스는 여러 종류의 디바이스 화면에 효율적으로 대응할 수 있다.

 

Xcode에서는 선택적으로 오토 레이아웃을 사용할지 말지 결정할 수 있는데, 오토 레이아웃을 사용하려면 옵션 설정이 필요하다. 

Xocde 인스펙터 탭의 첫번째에 있는 파일 인스펙터는 스토리보드 전반에 대한 정보를 설정하는 영역으로, 여기에서 [Use Auto Layout] 옵션에 체크를 해 주어야 한다. 만약 이 옵션이 체크되어 있지 않다면 오토 레이아웃 기능은 사용할 수 없다.

Xcode 12로 넘어오면서 위의 영역이 사라지고 자동으로 채택되는 것으로 바뀌었다.

 

오토 레이아웃은 객체들 사이의 제약 조건을 차례대로 추가하는 방식으로 구성한다. 따라서, 오토 레이아웃을 추가하기 전에 먼저 화면상의 각 객체들이 가질 제약조건을 먼저 정리해야 한다. 뷰 컨트롤러에 세 개의 뷰가 그림과 같이 있다고 했을 때, 디바이스별 레이아웃 및 가로세로 모드에서의 레이아웃을 처리하기 위해 필요한 각 뷰들의 제약 조건을 정의해 보면 다음과 같다.

빨강(A) 초록(B) 보라(C)

< 각 뷰들의 제약 조건을 정의 해보면 >

1. 뷰 A는 위쪽과 왼쪽 간격이 유지되어야 한다.

2. 뷰 B는 위쪽과 오른쪽 간격이 유지되어야 한다.

3. 뷰 C는 아래쪽과 왼쪽, 오른쪽 간격이 모두 유지되어야 한다.

4. 뷰 A와 B는 가로, 세로 길이가 같게 유지되어야 한다.

5. 뷰 A와 C는 세로 길이가 같게 유지되어야 한다.

6. 뷰 A와 B, 그리고 C는 모든 뷰 간격을 유지해야 한다.

 

제약 조건이 반드시 단일 객체에만 설정되는 것은 아니다. 필요에 따라서는 두 개 이상의 객체 사이 관계에 대한 제약 조건도 설정할 수 있다. 이같은 제약 조건들이 빈틈없이 채워지고 나면 오토 레이아웃은 이 조건들을 바탕으로 하여 화면 사이즈가 변하는 상황에서 적절한 레이아웃을 계산하고 유지하는 작업을 처리한다.

 

 뷰의 이름을 변경하여 제약조건을 보기 쉽게 하는법
뷰의 레이블 변경하는 법

 

Safe Area란?

안전 영역은 UI 구현시 iOS의 상태 바 등과 겹치지 않도록 하기 위해 제공되는 일종의 기준선으로, '겹치지 않게 화면을 구현하고 싶다면 가급적으로 지켜주어야 할 최소한의 영역' 입니다. UI 상에 객체를 배치할 때 화면과 객체 사이의 기준 간격을 제공하는 역할을 한다.

 

iOS 개발 초기에는 우리가 커스텀으로 구현한 UI가 상태 바나 네비게이션 바, 그리고 탭 바 등 UIKit에서 제공하는 각종 바에 의해 가려지는 경우가 많았다. 이를 방지하기 위해 애플은 iOS 7에서부터 UIViewController의 속성에 TopLayoutGuide과 BottomLayoutGuide 등의 레이아웃 가이드 요소를 추가하여 화면 구현시 가이드라인으로 사용할 수 있도록 지원하기 시작했다. 하지만 이들 가이드 요소가 여러 개로 나뉜데에 따른 불편함이 계속 제기되면서 iOS11부터는 이들 가이드 요소들이 모두 하나의 통합된 안전 영역 레이아웃 가이드(Safe Area Layout Guide)로 대체되었다.

 

안전 영역을 확인할 수 있는 방법은 Xcode 메뉴에서 [Editor] - [Canvas] - [Show Layout Rectangles]를 선택하면 된다. 빈 화면의 가장자리를 따라 약간의 여백을 두고 파란 색 가이드 라인이 표시될탠데, 이것이 바로 안전 영역이다.

 

iOS 11 기준으로 안전 영역은 가장 자리를 딸 ㅏ좌우측 0 포인트, 상하단 20포인트의 간격으로 지정된다. 다시 말해, 화면 좌우로는 가장자리 끝이, 상하단으로는 20 포인트까지 안전 영역에 해당한다는 거죠. 따라서 만약 화면 상단의 안전 영역에 맞추어 객체를 배치한다면 해당 객체의 Y좌표 위치는 20 포인트로 설정될 것이다.

 --> 안전 영역은 점선으로 나타나는데, iOS 14에서 확인 결과 좌우는 안전 영역이 잡히는 반면 상하는 안전영역이 잡히지 않음을 확인할 수 있었다.

안전영역에 대한 부분은 예를들면 실제 좌표가 20 포인트라고 하더라도 제약 조건상에서 안전영역의 20포인트 +20이 아니라 'Safe Area.top'으로 표시되는 점에 주의해야 한다.

즉, Safe Area.top는 안전영역의 포인트를 기본적으로 담고 있다는 것에 유의하자

 

 

실습에서 각 방향에서 선택한 방향에 연결해줄 제약조건

 

 

Equal Widths : 두 개 이상의 객체가 선택되어 있을 때만 활성화되는 메뉴로서, 선택된 객체들의 가로 길이를 동기화하는 역할을 한다. 어느 한쪽의 가로 길이가 변경될 경우 나머지 객체의 가로 길이도 동일하게 변경된다. 만약 이 제약조건이 추가된 후 실제로도 양쪽 뷰의 길이가 일치한다면 양쪽 객체의 가로 길이가 같음을 나타내는 표시가 추가된다.

 

Equal Heights : 이 제약 조건은 화면 사이즈가 변경될 때 뷰 A의 세로 길이에 대한 기준을 잡아준다. 이 설정을 추가하지 않으면 뷰 A는 어느 길이만큼 뷰가 늘어나야 하는지 명확하게 추론할 수 없다. 하지만 이 설정 덕택에 뷰 A의 세로 길이는 다음의 공식으로 얻을 수 있다.

 뷰 A의 세로 길이 = (화면의 세로길이 - 뷰사이의 간격들) / 2

 

 ++ (추가개념) ++

만약 두 객체가 존재할 때, ctrl 누른 채 드래그를 하여 제약조건을 줄탠데 직선으로 내릴떄와 대각선으로 내릴때 나타나는 팝업창이 다르다. 왜냐하면, Xcode는 드래그 방향에 맞는 제약 조건들만 필터링하여 보여주기 때문인데, 그래서 드래그 방향이 영향을 미친다. 그렇지만 우리는 우리가 원하는 제약조건을 선택하면 되니 넘 걱정하지는 말자.

 

+ 코드에 대한 추가 설명 +

뷰 A와 뷰B의 Width Heights를 설정하였다고, 뷰A와 뷰C의 Equal Heights를 연결하였다면, 뷰B와 뷰C의 Equal Heights를 연결할 필요는 없는데, 왜냐하면 연역적 추론 방식에 의해 뷰B와 C의 높이는 동기화 된다. 따라서 따로 별도로 설정을 추가할 필요는 없다.

 

Horizontal Spacing : 제약 조건은 선택된 객체들 사이의 수평 간격을 고정하는 역할을 한다. 덕분에 A와 B사이의 간격이 설정된다.

Vertical Spacing : 제약 조건은 선택된 객체들 사이의 수직 간격을 고정하는 역할을 한다. 

 

만약에 우리가 제약조건을 설정나고 난 후, 스토리보드에서 객체들을 움직였다고 가정해보자.

그러면 warning(노란 삼각형) 이 뜬 모습을 확인할 수 있는데, 4가지 항목이 나타난다.

 

레이아웃 완성

레이아웃 완성에 대한거 손으로 재정리!!

레이아웃 손으로 정리!

 

제약 조건 설정창

 

설정창의 각 항목은 레이아웃 경고를 어떻게 처리할 것인지 선택할 수 있게 도와준다. 선택한 항목에 따라 오토 레이아웃 설정이 변경되거나, 혹은 스토리보드상의 객체 위치나 크기가 변경될 수도 있다. 개별 옵션 항목에 대해 알아보자

 

- Update frames : 레이아웃 제약 조건을 기준으로 스토리보드상의 객체 위치나 크기 등을 수정한다.

- Update constraints : 현재 스토리보드상의 객체 위치나 크기를 기준으로 레이아웃 제약 조건을 수정한다. 두 객체의 크기가 다른 상태라면 Equal Widths, Equal Heights 등의 제약조건은 수정되지 않는다.

- Reset to suggested constraints : 현재 설정된 레이아웃 제약 조건을 모두 제거하고 스토리보드 상의 객체 위치를 기준으로 인터페이스 빌더의 판단에 따라 임의로 레이아웃 제약 조건을 설정한다.

- Apply to all views in container : 이 옵션에 체크하면 선택한 옵션이 뷰 컨트롤러 내 모든 뷰에 적용된다. 그렇지 않으면 대상 뷰에 한하여 적용된다.

 

오토 레이아웃을 설정하고 나면 회전이나 다양한 하면 크기에도 유연하게 대응하는 모습을 보여준다.

이와는 달리, 객체의 가로 세로 크기를 유지한 채로 화면의 변화에 따라 간격을 늘리거나 줄이고 싶을 수도 있다. 이때는 간격 대신 가로세로의 크기에 대한 제약 조건을 추가하면 된다.

방법은 어렵지 않은데 해당 뷰를 선택한 다음, 자기 자신을 벗어나지 않는 범위 내에서 우클릭 드래그하면 팝업 메뉴가 나타나는데, 여기서 Width, Height 또는 Aspect Ratio를 선택한다. Width, Height는 각각 객체와 가로와 세로 크기를 고정하는 제약 조건이며 Aspect Ratio는 가로나 세로의 길이를 기준으로 나머지 하나의 길이 비율을 일정하게 유지는 제약 조건이다.

자신의 내부로 드래그

 

오토 레이아웃에는 드래그를 통해 간격이나 크기 말고도 수평 또는 수직 정렬을 가능하게 해 주는 기능도 있다. 이 기능은 메뉴에 포함되어 있다. 이 기능은 메뉴에 포함되어 있는데, [Editor] -> [Align] 메뉴를 열어보면 이에 관련된 정렬 기능을 찾아볼 수 있다. 이 기능은 뒤에서 다시 등장하므로, 지금은 자세한 설명을 생략하고, 뒤에 더 작성하도록 하겠다.

 

제약 조건을 한 번에 설정하기

 

지금까지 위에 학습한 내용은 드래그를 통해 제약 조건을 추가하는 방식은 명확하고 쉽지만 하나씩 설정해야 하기 때문에 다소 불편하다. 설정해야 할 제약 조건이 많다면 그야말로 노가다 작업인 셈이다. 그래서 Xcode에서는 이를 조금 더 편하게 할 수 있는 방법을 제공한다. 인터페이스 빌더 아래쪽에 보면 여러개의 아이콘이 있는데, 이들 아이콘 각각은 제약 조건과 관련한 기능들을 담고 있다. 아이콘을 눌러 팝업되는 창을 이용하면 한꺼번에 여러 개의 제약 조건을 설정할 수 있다.

제약 조건 알림 설정창

전체 다섯 개의 아이콘 중에서 현재 그림에서 활성화되어 있는 2번째 아이콘에서 5번째 아이콘까지 순서대로 스택, 정렬, 핀 그리고 이슈해결을 담당한다. 객체의 중앙에 배치하거나 다른 객체와 맞추어 가지런히 놓을 때 사용하는 메뉴가 '정렬'이라면 '핀'은 앞에서 우리가 처리했던 간격을 고정을 의미한다. 핀을 꽂아 더이상 간격이 움직이지 못하도록 고정하는 의미다. 마지막 '이슈 해결'은 오토 레이아웃을 설정하면서 발생하는 오류나 경고창을 해결할 때 쓰이는 기능이다.

 

핀 설정 아이콘을 클릭하여 새 제약 조건을 추가

앞서 다루어본 오토 리사이징 설정과 유사한 성격의 인터페이스이다. 중아엥 위치한 작은 사각형은 인터페이스 빌더에서 현재 선택되어 있는 객체를 의미하고, 전후좌우로 둘러싼 H 빔 형태의 간격 표시는 객체를 포함하고 있는 상위 객체와의 간격 설정을 의미한다. 간격 표시가 희미하면서 점선인 것은 설정되지 않았다는 뜻이며, 진한 실선으로 표시된 것은 해당 부분을 제약 조건으로 추가한다는 것을 나타낸다.

 

드래그를 통해 작업하는 것과 같은 효과를 낸다!

여기서 주의할 점은 설정창을 다시 열었을 때, 조금 전 추가한 제약 조건들이 하나도 표시되지 않는다. 다시 설정하는 것이 아니라 설정창을 다시 열어도 나타나지 않아 기존 내용이 제대로 등록되지 않았다고 오인하고 설정 작업을 다시 진행하는 경우도 있는데, 이렇게 하면 안된다. 이미 추가된 제약 조건을 중복 추가하는 결과가 되어버리니까요. 그러니 설정창을 열었을 때 아무 것도 표시되지 않는다고 하더라도 다시 추가하는 일이 없도록 해야한다. 정 찜찜하다면, 문서 개요창을 열어 제약 조건이 제대로 추가되어 있는지를 확인하길 바란다.

설정창을 이용한 예시

뷰A는 위쪽과 왼쪽을 선택하여 [Add 2 Constraints]를 클릭하고 뷰B는 위쪽, 왼쪽, 오른쪽 [Add 3 Constraints]를 제약 조건으로 추가한다. 이때 뷰B에서 추가해준 왼쪽 간격은 뷰A와의 간격을 의미한다. 기존에 뷰 A에서 B로 드래그하여 추가했던 Horizontal Spacing이 여기에서는 왼쪽 간격 설정으로 대체되는 것이다. 뷰 A에서 간격을 설정할 경우 뷰 A의 뒤쪽 경게가 뷰 B의 앞쪽 경계와 N만큼의 간격을 유지하는 것이 되고, 뷰B에서 간격을 설정할 경우 뷰B의 앞쪽 경계가 뷰 B의 뒷쪽 경계와 N만큼의 간격을 유지하는 것이 되는데, 둘은 결국 주체만 바꾼 같은 의미이기 때문이다. 

 

마지막 뷰 C에는 상하좌우 모두에 체크한 다음 [Add 4 Constraints]를 클릭하여 제약 조건을 등록한다.

뷰C에도 제약조건 연결

뷰 C에서 추가한 하단 및 좌우측 간격은 모두 상위 뷰를 대상으로 하는 제약 조건이지만, 상단 간격은 뷰 A 및 B에 대한 제약 조건을 의미합니다. 설정된 제약 조건이 표시된 모습은 위의 사진과 같다.

 

다음으로 해야하는 것은 뷰 A와 뷰 B를 동시에 선택하고 [Equal Widths] 와 [Equal Heights] 를 준 설정한 후 뷰A와 뷰C를 선택한 후 [Equal Heigths]를 설정해주면 아래 그림처러 빨간색 오류는 사라지고 설정된 모습을 확인할 수 있다.

제약조건을 모두 설정하고 난 후 모습