iOS/개념 & 개발

[iOS] 화면 방향에 따라 다른 레이아웃 적용하기 - viewWillTransition

유정주 2022. 9. 15. 11:51
반응형

화면 방향에 따라 다른 레이아웃 적용하기

세로 레이아웃과 가로 레이아웃이 다른 앱을 쉽게 볼 수 있습니다.

대표적인 기본 앱은 계산기가 있죠.

스마트폰을 가로로 회전시키면 세로 레이아웃에 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

https://www.hackingwithswift.com/example-code/uikit/how-to-animate-when-your-size-class-changes-willtransitionto

https://sujinnaljin.medium.com/ios-%ED%99%94%EB%A9%B4-%EB%B0%A9%ED%96%A5%EC%97%90-%EB%94%B0%EB%A5%B8-collectionview-cellsize-%EB%B3%80%EA%B2%BD-cc12348a9755


아직은 초보 개발자입니다.

더 효율적인 코드 훈수 환영합니다!

공감 댓글 부탁드립니다.

 

 

 

반응형