화면 방향에 따라 다른 레이아웃 적용하기
세로 레이아웃과 가로 레이아웃이 다른 앱을 쉽게 볼 수 있습니다.
대표적인 기본 앱은 계산기가 있죠.
스마트폰을 가로로 회전시키면 세로 레이아웃에 View가 추가된 레이아웃으로 변경됩니다.
스마트폰만 지원한다면 "세로로 고정시키면 되지 않나?"라고 생각할 수 있지만,
아이패드까지 지원한다면 화면 방향에 따라 적절한 레이아웃을 고려하는 것이 사용자 경험을 증가시킬 수 있습니다.
생각해보세요!
계산기 앱에서 가로 방향에서만 나오는 여러 수식 버튼들이 세로 방향에서도 나오고,
그 영향으로 버튼이 콩알만 해지면 훨씬 불편해지겠죠??
(여러 수식들로 멀미가 나는건 덤..)
viewWillTransition(to:with:)
이럴 때 사용할 수 있는 메서드가 viewWillTransition(to:with:) 입니다.
화면 방향이 변경될 때 ViewController에게 알려주는 메서드에요.
(근데 하단의 Required. 는 어떤 의미일까요?;; 처음 보는 표시에 당황했어요. 혹시 뭔지 아시는 분은 댓글 달아주시면 감사하겠습니다.)
viewWillTransition 메서드는 정확히 말하면 "view controller의 view의 size가 변경될 때 호출되는 메서드"인데요.
그 예시 중 하나 window가 회전할 때입니다.
아이패드에는 앱을 두 개 띄울 수 있죠?
그때도 view 사이즈가 변경되면서 viewWillTransition 메서드가 호출됩니다.
파라미터 살펴보기
size 파라미터는 container View의 새로운 size입니다.
세로일 때 300 * 500인 화면을 가로로 회전시키면 500 * 300이 됩니다.
이 size 값을 계산해서 레이아웃을 다시 계산해서 배치시키는 것입니다.
아래 간단한 실습에서 진짜 그런지 확인해봐요.
coordinator 파라미터는 사이즈 변경을 관리하는 coordinator 객체라고 하는데요.
이 객체를 이용하면 회전 애니메이션을 바꾸거나 진행 중인 변경에 대한 정보를 얻을 수 있다고 합니다.
근데 회전에 대한 애니메이션은 비슷한 이름인 willTransition(to:with:) 코드가 더 많이 나오더라구요.
viewWillTransition과 willTransition의 차이점을 찾아보니
viewWillTransition는 ViewController의 view의 size가 변경될 때 호출되는 것으로 장치 회전을 판단할 때 사용됨이 적절하고, 특정 Collection이 변경될 때만 호출되고 싶다면 willTransition을 사용하는 것이 적절하다고 합니다.
특히, 아이패드에서는 화면을 회전한다고 willTransition이 호출되지 않으니 반드시 viewWillTransition을 사용해야 된다고 하네요.
진짜 호출이 안 되는지 확인을 해보려고 아래 코드를 시뮬레이터에서 동작시켜 보았는데요.
로그를 보면,
아이폰에서는 화면을 회전시키면 둘 다 호출이 되었지만
아이패드에서는 진짜로 viewWillTransition만 호출되었습니다.
아이패드에서 화면을 시킬 때는 view의 size는 변경되지만 collection이 변경되는 것은 아니라고 합니다.
그래서 viewWillTransition만 호출이 됩니다.
이것으로 공식 문서 정의의 중요성을... 다시 한 번 느끼고 갑니다 ㄷㄷ
실습해보기
viewWillTransition 메서드 안에 화면이 회전될 때 동작할 코드를 넣으면
화면 방향에 따라 다른 레이아웃을 구현할 수 있겠죠??
UIDevice.current.orientaion을 이용해 현재 기기의 회전 방향을 얻을 수 있습니다.
이를 이용해 회전에 따라 label의 텍스트를 바꿔보겠습니다.
private func changeLayout() {
if UIDevice.current.orientation.isLandscape {
landscapLayout()
} else {
portraitLayout()
}
}
private func landscapLayout() {
label.text = "Landscape"
}
private func portraitLayout() {
label.text = "Portrait"
}
landscape일 때는 Landscape로, portrait일 때는 Portrait로 Label의 텍스트를 바꾸겠습니다.
위 코드를 viewWIllTransition에 넣으면 완료에요.
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
changeLayout()
}
진짜 간단하죠?
동작도 제대로 되는 것을 볼 수 있습니다.
감사합니다!
참고
https://developer.apple.com/documentation/uikit/uicontentcontainer/1621466-viewwilltransitionhttps://developer.apple.com/documentation/uikit/uicontentcontainer/1621511-willtransition
아직은 초보 개발자입니다.
더 효율적인 코드 훈수 환영합니다!
공감과 댓글 부탁드립니다.