[iOS]CALayer 응용편 (1)

신용철·2020년 10월 5일
0

iOS_View

목록 보기
5/11

1. Layer의 계층구조 설정하기

아래 method를 사용하면 view의 계층구조와 별개로 layer의 계층 구조를 설정할 수 있습니다. 단, 주의할 점은 View의 계층구조에 상충되어서는 안된다는 점입니다. method 이름으로 사용법을 충분히 알 수 있으므로 추가적은 설명은 하지 않겠습니다.

  • addSublayer( _:)
  • insertSublayer( _: at:)
  • insertSublayer( :below:), insertSublayer( :above:)
  • replaceSublayer( _:with:)
  • removeFromSuperlayer

2. Layer의 drawing 순서

  • layer는 기본적으로 뒤에서 앞으로 그리는 순서를 갖는 규칙을 갖지만 이것이 절대적인 것은 아닙니다. zPosition과 CGFloat속성에 의해 순서가 정해지기도 합니다.

  • zPosition이 있는 경우: 여러 개의 sublayer가 있고 이 layer들이 서로 siblings일 경우, zPosition이 낮은 것부터 우선하여 그려집니다. 참고로 zPosition의 기본값은 0.0 이고 최대값은 1입니다. zPosition은 유동적인 layer의 배열을 해야할 때 매우 편리합니다. 카드 게임을 구현한다고 생각해보시면 좋을 것 같습니다. 특정 이벤트에 따라 카드들이 서로 겹처보이는 순서가 정해진다고 할 경우에 zPostion을 사용하면 카드들의 배치 순서를 유동적으로 변경할 수 있어 편리합니다.

	let card = UIView()
	card.layer.zPostion = 1

3. sublayer의 Positioning

  • layer도 view와 마찬가지로 bounds 속성을 통해 coordinate와 size를 표현할 수 있습니다. 하지만view와는 달리 superlayer의 내부에서 sublayer의 position을 표시할 때 center값을 사용할 수 없습니다. layer에는 center값이 없기때문이죠. layer에서는 center값 대신 position과 anchorPoint라는 두 속성을 조합해서 사용합니다.

  • 갑자기 두 개념이 나와서 헷갈릴 수 있지만 쉽게 비유를 해보겠습니다. 칠판 위에 종이를 핀으로 고정한다고 생각해봅시다. 이 경우 칠판이 superlayer이고 종이가 sublayer라고 하겠습니다. 핀으로 종이를 고정시킬 때 핀과 종이가 접촉하는 부분이 anchorPoint이고 핀과 칠판이 닿는 부분이 position 입니다.

  • anchorPoint는 (0, 0) ~ (1, 1) 값으로 설정할 수 있습니다. (0, 0)은 좌측 상단 꼭지점을 의미하며, (1, 1)우측 하단 꼭지점을 의미합니다. 그리고 (0.5, 0.5)는 중앙을 의미합니다. 위의 예를 계속해서 활용해보겠습니다. "종이의 좌측 상단의 꼭지점이 칠판의 중앙에 위치하게 해줘"라고 누가 주문을 했다고 합시다. 그러면 anchorPoint는 (0, 0)으로, position은 칠판의 중앙 좌표값으로 넣어주면 됩니다.

  • 아래 예제 그림의 왼쪽은 iOS기준이고 오른쪽은 OS X기준입니다(서로 y축 좌표값의 positive 방향이 반대입니다). 아래 그림에서 anchorPoint가 (0, 0)이고 position이 (40, 60)인 부분을 보면 sublayer의 좌측 꼭지점이 superLayer의 (40, 60)에 배치되는 것을 볼 수 있습니다.

  • layer의 frame에 대해 간략하게 알아보겠습니다. layer에 있어 frame은 파생된 값으로 사실 쓸 일이 별로 없습니다. 파생된 값이라 함은 frame값은 bounds.size값과 position + anchorPoint로 계산해서 표현되기 때문입니다. 반대로 frame값을 설정(set)하면 bounds.size와 position이 설정됩니다. 하지만 이 방법은 직관적이지 않기 때문에 사용을 피하는 것이 좋습니다. 그럼에도 frame이 가끔 편리하게 사용되는 경우가 있는데요. 바로 superlayer에 sublayer를 완전히 겹치도록 만들고 싶을 때입니다. 이 때는 sublayer의 frame을 superlayer의 bounds와 같게 설정해주면 됩니다.

  • 참고사항: layer를 코드로 구현할 때는 frame과 bounds값이 CGRect.zero로 설정되어있기 때문에 width, height값을 반드시 세팅하고 사용해야합니다. 안그러면 화면에 표시되지 않습니다. 또한, layer의 인스턴스화 method에는동일한 계층 구조에 있는 다른 CALayer를 기준으로 사용할 수 있는 convert( :from:) or convert( :to:) 메서드가 있습니다.

4. CAScrollLayer

  • CAScrollLayer는 layer.bounds의 origin값을 변경해서 layer를 재배치할 수 있는 CALayer의 subclass입니다.

  • 이름에 scroll이 있어서 user가 drag하는 것 처럼 생각할 수 있는데 그렇지는 않습니다. code를 통해 이동시키는 것입니다. 속성으로 선언되어있는 method들은 아래와 같습니다.

  • scroll(to:) : CAScrollLayer에서 직접 호출하는 method입니다. param으로 CGPoint를 넣으면 해당 포인트로 CAScrollLayer.bounds.origin이 이동합니다.

  • scroll( _:) : CAScrollLayer의 sublayer에서 호출하는 method입니다. 지정된 point로 sublyer의 좌측 상단 꼭지점이 위치하도록 CAScrollLayer.bounds.origin 값이 변경됩니다.

  • scrollRectToVisible(_:): 역시 CAScrollLayer의 sublayer에서 호출하는 method입니다. sublayer.bounds의 Rect가 모두 CAScrollLayer의 테두리 안으로 들어올 수 있도록 CAScrollLayer의 bounds.origin값이 변경됩니다.

5. Layer Delegate

  • CALayer의 delegate 속성은 CALayerDelegate를 채택한 모든 class에서 인스턴스화 하여 사용할 수 있습니다.

  • 보통 view의 root layer(기본 layer)가 아닌 경우에 layer의 layout이나 drawing에 다른 객체를 제공하기 위해 사용합니다. 이 부분에 대한 자세한 내용은 별도의 포스트로 자세하게 다루겠습니다.

  • 주의할 점이 있습니다. 바로 UIView와 root layer의 관계를 훼손하지 말아야 한다는 점인데요. 이 말은 UIView는 절대로 root layer이외의 다른 layer의 delegate가 되어서는 안되며, 동시에 root layer역시 다른 UIView를 delegate로 만들면 안된다는 것을 의미합니다. 이 경우 drawing이 제대로 작동하지 않습니다. UIView - root layer의 1:1 관계는 절대로 건드려서는 안됩니다.

6. Layer의 Layout

  • autolayout은 root layer에만 적용 됩니다. root layer가 아닌 다른 sublayer들은 autolayout을 사용할 수 없습니다. 즉, 모두 수동으로(코드로) layout을 설정해야 합니다.

  • layer의 bounds값이 바꼈거나 setNeedsLayout를 호출 할 때 sublayer의 layout이 필요한 경우가 있는데요. 이럴 때는 layer의 delegate에서 layoutSublayer(of:)를 호출하면 됩니다.(root layer인 경우에는 UIView가 delegate입니다.) 참고로, layoutSublayer는 view의 layoutSubview가 호출된 이후에 호출됩니다.

profile
iOS developer

0개의 댓글