UIView의 위치/크기 동적 변경 및 layoutSubviews 메소드 호출 시점

UIView 의 크기가 변경되면, 크기가 변경된 UIView 의 서브뷰들은 위치와 크기가 조정되어야 한다. UIView 는 이를 위해 자동과 수동으로 UIView 의 layout을 조정하는 방법을 제공한다.

다음의 이벤트에 레이아웃 변경이 발생한다.

  • UIView의 bounds 사이즈 변경 
  • root view의 변화를 유발하는 Interface orientation (세로모드, 가로모드 등)변화.
  • UIView의 view layer 변화 유발 또는 layout을 요청하는 Core Animation sublayers 의 설정
  • UIView의 setNeedsLayout 또는 layoutIfNeeded 메소드가 호출될 경우
  • UIView의 layer에서 setNeedsLayout 이 호출되 경우. (UIView는 Cora Animation Layer 인 CALayer 와 결합하여 화면에 컨텐츠/에니메이션을 표시. UIView 에는 layer 속성이 존재)

Autoresizing Rule을 이용한 자동 layout 변경

UIView의 autoresizesSubviews 속성값을 통해 서브뷰들의 layout을 변경할 수 있다.

속성값이 YES로 설정되어 있으면, UIView는 서브뷰들의 autoresizingMask 속성을 이용하여 서브뷰들의 위치와 크기를 변경시킨다. autoresizingMask 기본값은 UIViewAutoresizingNone으로 부모 UIView의 레이아웃 변경에 아무런 영향을 받지 않는다.

< from iOS developer library >

AutoresizingMask 속성에는 위 그림의 값을 설정할 수 있다. 각 요소는 OR 조건 (||) 으로 동시 적용이 가능하다. (각 상수에 대한 자세한 내용은 View Programming Guide for iOS 참고)

수동 Layout 변경

autoresizing rule을 통한 레이아웃 변경이 모든 서브뷰에 적용되면, UIKit은 UIView에 수동으로 조절할 수 있는 기회를 제공하는 의미에서 layoutSubviews 메소드를 호출한다.

만약 autoresizing rule 을 통한 서브뷰의 자동 레이아웃 변경이 의도한 바와 다르다면, layoutSubviews 메소드를 override 하여 추가적인 조정을 할 수 있다. (UIView를 상속하는 custom view를 만들어야 한다.)

layoutSubviews 내에서 다음과 같은 행위들이 가능하다.

  • 서브뷰의 size 및 position 변경
  • 서브뷰 또는 CALayer 의 추가/삭제
  • 서브뷰의 setNeedsDisplay 또는 setNeedsDisplayInRect: 메소드를 호출하여 서브뷰를 다시 그리도록 유도

아래 그림은 layoutSubviews 가 언제 호출되는지 실험한 데이터이다. (출처 :  when does layoutSubviews get called  )

< from Logic High Blog >

UIView 의 기준점만 변경될 때는 호출되지 않지만, 크기가 변경될 경우에는 호출된다. addSubview에서는 서브뷰와 부모뷰의 layoutSubview가 모두 호출된다. 이때 추가되는 서브뷰와 같은 레벨의 또다른 서브뷰가 존재하면, 그 서브뷰의 layoutSubviews도 호출된다.  UIScrollView 로 스크롤 할 때에도 layoutSubviews 메소드는 호출된다. 자세한 내용은 출처 블로그 내용을 참고하자.

본인도 별도로 간단한 테스트를 해봤다.

UIView 를 상속한 커스텀 클래스 UIView A 는 UIView 1 을 자식 요소로 같는다. UIView 1 은 UIView 2를 자식요소로 갖는다.  여러 케이스에서 UIView A 의 layoutSubviews가 호출되는지 확인하였다.

  • UIView A 원점만 변경 : 호출 안됨
  • UIView A 사이즈만 변경 : 호출됨
  • UIView 1 원점만 변경 : 호출안됨
  • UIView 1 사이즈만 변경 : 호출됨
  • UIView2 원점만 변경 : 호출안됨
  • UIView2 사이즈만 변경 : 호출안됨
  • UIViewA setNeedsLayout : 요청시마다 호출
  • UIViewA layoutIfNeeded : 호출 안됨. (변경점이 없으면 호출 안됨)
  • UIView 1 setNeedsLayout : 호출 안됨
  • UIView 2 setNeedsLayout : 호출안됨

본인의 테스트에 의하면 자식 요소의 사이즈 변화도 부모 요소의 layoutSubviews 메소드 호출을 유도한다. 직접적인 자식요소가 아닌 자식요소의 자식요소의 크기 변화는 부모 요소에 영향을 미치지 못한다. setNeedsLayout 메소드는 receiver 객체의 layoutSublayers 메소드를 호출한다.

* Reference : Adjusting the Size and Position of Views at Runtime in  View Programming Guide for iOS

Advertisements
Leave a comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: