컴포넌트를 좋은 위치에 조정하는 방법을 다룹니다
SwiftUI를 사용한다면 버튼이나 텍스트 같은 요소들을 화면에서 원하는 곳에 위치시키고 싶으면 offset modifier 또는 position modifier 를 사용하여 컨텐츠의 위치를 이동시킬 수 있습니다.
뷰 레이아웃 만들기
다음 예제는 뷰를 배치하는 방법을 설명하는 뷰를 제공하며, ZStack 내에서 구성된 뷰의 대략적인 레이아웃을 제공합니다. ZStack에는 겹쳐진 원 이미지가 있는 사분면이 포함되어 있습니다:
struct Crosshairs: View { ... } // Draws crosshairs.
struct Quadrant: View {
var body: some View {
ZStack {
Crosshairs()
Rectangle()
.stroke(Color.primary)
Image(systemName: "circle")
}
.frame(width: 160, height: 160)
}
}
뷰의 컨텐츠 이동시키기 (offset)
뷰에서 위에서 만든 내부에 원을 포함한 사분면을 이동시키기 위해서는 offset modifier를 사용해야 합니다.
offset modifier를 사용하면 기본 가운데 위치에서 시작하여 원하는 곳으로 컨텐츠의 위치를 이동시킬 수 있습니다.
SwiftUI 에서는 X는 가로축을 의미하며 오른쪽으로 갈수록 값이 양의 수로 커지고 왼쪽으로 갈수록 값이 음의 수로 작아집니다.
반대로 Y는 세로축을 의미하며 아래로 갈수록 값이 양의 수로 커지고 위로 갈수록 값이 음의 수로 작아집니다.
다음 예제 코드는 원을 가운데로부터 40 포인트만큼 이동시켰습니다.
struct Quadrant: View {
var body: some View {
ZStack {
Crosshairs()
Rectangle()
.stroke(Color.primary)
Image(systemName: "circle")
.offset(x: 40.0, y: -40.0)
}
.frame(width: 160, height: 160)
}
}
아래 그림을 확인했을 때 x축이 40만큼 커졌으므로 오른쪽으로, y축이 -40만큼 작아졌으므로 위로 이동한 것을 확인할 수 있습니다.
뷰 컨텐츠를 명시적으로 배치시키기 (position)
뷰 내에서 요소를 명시적으로 배치하려면, position(x:y:) 뷰 수정자를 사용합니다. position modifier는 부모 뷰가 컨텐츠를 배치하는 위치를 재정의합니다. 이 수정자는 뷰의 원점에서 offset된 위치에 뷰를 렌더링하며, 이는 부모 뷰가 선택한 위치에서 뷰를 이동시키는 offset 수정자와 다릅니다. postion modifier는 offset 수정자와 동일한 x, y 좌표를 사용하며 뷰의 크기에 영향을 미치지 않습니다.
struct Quadrant: View {
var body: some View {
ZStack {
Crosshairs()
Rectangle()
.stroke(Color.primary)
Image(systemName: "circle")
.position(x: 144, y: 80)
}
.frame(width: 160, height: 160)
}
}
offset 과 position 의 차이
위에서 offset과 position의 차이를 확인해보았습니다. 위에 글을 정리해서 좀 더 알기 편하게 정리해보겠습니다.
offset
- 원리: 컨텐츠를 대상으로 x, y 의 값을 사용하여 특정 거리만큼 이동시키는 데 사용됩니다.
- 기준점: 뷰(컨텐츠)의 위치를 기준으로 이동합니다.
- 좌표: 상대적인 좌표를 사용합니다. 부모 뷰의 좌표 시스템에서 이동 거리를 지정합니다.
2개의 ZStack을 만들고 이후 각각 ZStack에 Image를 만들어 offset을 설정하여 어떻게 변화하는지 확인해봅니다.
struct Quadrant: View {
var body: some View {
ZStack {
ZStack {
Crosshairs()
Rectangle()
.stroke(Color.primary)
Image(systemName: "circle")
.offset(x: 0, y: 0)
}
.frame(width: 120, height: 120)
.background(Color.gray)
Image(systemName: "circle")
.resizable()
.offset(x: 0, y: 0)
.frame(width: 50, height: 50)
}
.frame(width: 360, height: 360)
.background(Color.blue)
}
}
결과
다음 그림을 확인해본 결과 offset 이란 부모 뷰의 가운데를 기준으로 위치를 이동하는 것이라고 이해할 수 있겠습니다.
x:0, y:0 이란 부모 뷰의 가운데를 의미
position
- 원리: 부모 컨텐츠를 대상으로 x, y 의 값을 사용하여 특정 거리만큼 이동시키는 데 사용됩니다.
- 기준점: 부모 뷰(컨텐츠)의 위치를 기준으로 이동합니다.
- 좌표: 절대적인 좌표를 사용합니다. 부모 뷰의 좌표 시스템에서 중심점을 지정합니다.
2개의 ZStack을 만들고 이후 각각 ZStack 에 Image를 만들어 position을 설정하여 결과가 어떻게 되는지 확인해봅니다.
struct Quadrant: View {
var body: some View {
ZStack {
ZStack {
Crosshairs()
Rectangle()
.stroke(Color.primary)
Image(systemName: "circle")
.position(x: 0, y: 0)
}
.frame(width: 120, height: 120)
.background(Color.gray)
Image(systemName: "circle")
.position(x: 0, y: 0)
}
.frame(width: 360, height: 360)
.background(Color.blue)
}
}
결과
결과를 확인해보면 해당 position modifier의 상위 뷰를 기준으로 위치가 설정되는 것을 확인할 수 있습니다.
x:0, y:0 이란 좌측 상단을 의미
전체 코드
import SwiftUI
struct Crosshairs: View {
var body: some View {
GeometryReader { geometry in
let width = geometry.size.width
let height = geometry.size.height
let midX = width / 2
let midY = height / 2
Path { path in
// Horizontal line
path.move(to: CGPoint(x: 0, y: midY))
path.addLine(to: CGPoint(x: width, y: midY))
// Vertical line
path.move(to: CGPoint(x: midX, y: 0))
path.addLine(to: CGPoint(x: midX, y: height))
}
.stroke(Color.primary, lineWidth: 1)
}
}
}
struct Quadrant: View {
var body: some View {
ZStack {
Crosshairs()
Rectangle()
.stroke(Color.primary)
Image(systemName: "circle")
// .position(x: 0, y: 0)
.offset(x: 0, y: 0)
}
.frame(width: 160, height: 160)
}
}
#Preview {
Quadrant()
}
'SwiftUI' 카테고리의 다른 글
SwiftUI - 나만의 SPM 만들어 사용해보기 (0) | 2024.08.08 |
---|---|
SwiftUI - DragGesture 사용해서 화면 드래그하는법 (0) | 2024.08.07 |
Swift - Sheet, presentation 뒤에 배경하고 상호작용 presentationBackgroundInteraction (0) | 2024.07.18 |
DisclosureGroup 로 접는 뷰 만들기 (0) | 2024.07.13 |
Preview에서 SwiftData 사용하기(crashed due to an uncaught exception) (0) | 2024.06.28 |