안녕하세요. 린다입니다.
저번 WWDC 영상을 보면서 혼자 이것저것
레이아웃 프로세스에 대해서 공부했던? 확인했던..?
예제들을 정리해보려고 합니다.
SwiftUI의 레이아웃 프로세스에 관한 글을 안 읽어보셨다면
(https://sy-catbutler.tistory.com/67)
읽고오시는걸 추천드립니다 !!
그리고 추가적으로 해당 글에서는 offset과 position에 대해서도 다뤄보려고 해요.
두개의 차이점이 무엇인지도 정리해보려고 합니다.
1. offset
공식문서에 있는 Offset의 설명을 보면
Offset this view by the horizontal and vertical amount specified in the offset parameter.
이 보기를 오프셋 매개변수에 지정된 수평 및 수직 양으로 오프셋합니다.
인 것을 알 수 있다. 즉, 설정한 값 만큼 수평/수직으로 위치 값을 계산해서 배치해준다고 생각하면 될듯.
해당 예제를 레이아웃 프로세스와 함께 offset이 어떻게 적용되는지 순서를 알아봅시다.
레이아웃 순서) RootView -> background(pink) -> offset -> background(purple) -> Text
1. RootView > background, offset, background(중립) > Text부터 시작
- Text: 나는 내 글자 길이만큼 필요해
- Text: Text의 글자 길이만큼 bounds를 background(purple)에게 반환
2. Text의 bounds에 맞춰서 background(purple)의 bounds 설정되고 background(purple)은 본인의 중앙에 뷰를 배치
3. offset offset도 레이아웃 중립이기 때문에 똑같은 bounds의 값을 가지며, offset와 별개로 원래의 dimensions은 유지됨
- 그 상태에서, 자신의 좌표공간 내에서 offset 만큼 계산하여 배치함
- 레이아웃 bounds != 좌표공간내의 배치, 구분해서 생각할것
4. offset > background(pink)에게 bounds를 전달
- offset bounds == backgound(pink) bounds (background는 중립이기 때문에 해당 bounds 만큼을 사용)
- background(pink)는 해당 뷰를 본인의 뷰 중앙에 배치
5. background(pink) > RootView,
- RootView한테 결정된 bounds 보고하면 RootView가 배치
- 여기서 offset은 기본 geometry를 변경하지 않고 실제 뷰를 렌더링해야하는 위치를 변경한다.
3번의 추가 설명은 해당 공식문서를 참고!
(The original dimensions of the view aren’t changed by offsetting the contents)
(https://developer.apple.com/documentation/swiftui/making-fine-adjustments-to-a-view-s-position)
1 - 1. offset 2번째 예시
레이아웃 순서) RootView -> background(yellow) -> offset -> background(green) -> text
1. Text: 나 내 문자 길이만큼 쓸게
- Text count == Text bounds > background(green) 에게반환
- Text bounds == background bounds
2. background(green)은 green(중립)에게 물어보고 반환을 받은 뒤 해당 bounds를 자신의 뷰 중앙에 배치
3. background(green)은 offset에게 bounds 반환
- background(green) bounds == offset bounds
- offset은 100, 100에 레이아웃 배치함
4. offset bounds > background(yellow)
- background(yellow)는 해당 bounds만큼 사용하면서 자신의 뷰 중앙에 배치
5. background(yellow) > frame
- frame은 200, 200 만큼 필요하고(bounds), 자식들은 bottomTrailing에 배치한다고 반환
- * 5 -> 6 부분으로 인해서 yellow 와 text+green이 bottomTrailing 쪽으로 200, 200만큼 이동하게 됨
6. frame -> background(red)
- frame bounds == background(red) bounds
- background(red)는 본인 뷰의 중앙에 배치함
7. background(red) -> RootView) RootView: 자식 뷰의 결정에 따름
*(0,0)은 정말 0,0 에 위치해있습니다. 이해를 위해서 ZStack으로 추가해 놓은 뷰에요!
이 정도면 이제 offset + 레이아웃 프로세스 감을 잡았을 것이라고... 생각해요.
그럼 이제 Position를 확인해볼 시간..
2. Position
Position? : 이 뷰의 중심을 부모 좌표 공간의 지정된 지점에 배치함
레이아웃 순서) RootView > background(blue) > position > background(green) > Text
background(중립) > Position(사용 가능한 space를 모두 사용하는 View) > Position은 모든 영역을 다 사용한다고 선언
position -> background(green)(중립) 즉, 시작은 Text로 부터!
1. Text: 본인 길이만큼 사용한다고 반환
- Text bounds == background(green) bounds
2. Text > background(green)
- bounds를 동일하게 가져가면서, background(green) 본인의 뷰 중앙에 자식 뷰 배치
3. background(green)> Position
- Position은 사용 가능한 모든 영역을 사용하면서,
- 지정된 공간에(x:100, y:100에) backgrounds(green) + Text를 배치시킴
4. Position > background(blue)
- Position bounds -> background(blue) bounds 가 되면서 backgrounds는 blue가 됨
5. background(blue) -> RootView
- 이미 position을 통해서 좌표값이 픽스가 되었기 때문에 각 레이아웃 계층에서 자식 뷰를 중간에 배치하더라도
고정된 값에 올려진것을 중간에 계속 중복적으로 올리는 것을 의미함. - 즉 똑같이 올라감
*여기서 왜.. safeArea 까지 색상이 다 채워지지?
해당 블로그를 참고해서 알았습니다..
background의 ignoresSafeAreaEdges의 default가 .all 이기 때문입니다.
그래서 [] 처럼 설정을 해주면 safeArea가 제외하고 설정되어요!
2 - 1. Position 2번째 예시
레이아웃 순서)
RootView > background(red) > position > background(blue) > position > background(green) > Text
(이건 조금 읭? 스럽고 긴 설명이기 때문에 강조를 해봤어여..)
1. Text: 나 내 길이만큼 bounds 쓸게
- Text 길이 == Text bounds
- Text bounds > background(green)
2. Text bounds == background(green) bounds
- background(green)는 해당 bounds를 가지고 본인 뷰의 중앙에 뷰 배치
3. background(green) > position
- position은 전체공간을 사용할 수 있는 뷰 (bounds == 전체공간)
- bounds를 전체공간으로 가져가면서 지금까지의 background(green)을 200, 200에 배치함
4. position > background(blue)
- position bounds == background(blue) bounds
- background(blue)는 해당 뷰를 본인의 뷰 중앙에 배치
5. background(blue) > position
background(blue) bounds == position bounds
position은 전체 공간을 사용하면서 100, 100에 해당 뷰를 배치함
6. position > background(red)
- position bound == background(red)
- background(red)는 본인뷰의 중앙에 자식뷰 배치
7. background(red) > RootView
- RootView는 자식뷰의 레이아웃에 따름
간단한 예제로 레이아웃 프로세스를 연습해봤어요.
이렇게 정리하고 보니 그동안 이상하게 쌓이던 modifier의 이유를 .. 파악할 수 있는것 같슴니다..
혹시나.. 틀리게 알고 있는 부분이 있다면 말씀주세요!
그럼 오포끝!
'Swift > SwiftUI' 카테고리의 다른 글
SwiftUI로 Carousel 구현하기 (0) | 2024.07.17 |
---|---|
SwiftUI, Layout 프로세스를 알아보자3 (feat, Offset와 Position) (0) | 2024.03.28 |
SwiftUI, Layout과 Alignment을 알아보자 (2019 WWDC) (1) | 2024.03.28 |
SwiftUI, Custom TextEditor 만들기 (0) | 2024.03.20 |
SwiftUI, Line Height 명확하게 설정하기 (feat, linespacing) (0) | 2024.03.02 |