오늘 알아볼것은 SwiftUI에서 Grid입니다!!!
사실 지금까지 쓸 일이 없었고, 그냥 아 저런게 있구나 이렇게만 알고 있었거든여
근데 이번에 앱스쿨 과제를 만들때 한번 써볼까?? 싶어서 정리해봤습니다!! (
안하면 맨날 까먹어서 다시 찾아야함 ㅋㅋ
)
Grid
- 컨테이너에 뷰를 2차원 정렬하는 레이아웃임!!
LazyHGrid
- 수평으로 늘어나는 Grid임!!
- 그래서 가로로 스크롤이 가능한 뷰 컬렉션을 표현할 때 사용함!!
- 그래서 보통 ScrollView 랑 같이 쓰는거 같아여
사용하려면?
- 그리드에 포함될 열 항목의 배열을 생성해야 합니다.
GridItem 을 이용해서 아이템을 생성함!
let rows1 = [GridItem(.fixed(30))] // 1개의 열로 표현됨
let rows2 = [GridItem(.fixed(30)), GridItem(.fixed(30))] // 2개의 열
2. 그러면 이제 LazyHStack 을 이용해서 그리드를 표현하면 됨!!!
HGrid를 표현하기 위해서 ScrollView(.horizontal) 를 사용했습니다.
ScrollView(.horizontal) {
LazyHGrid(rows: rows, spacing: 50) {
ForEach(1...30, id: \.self) { value in
Text("\(value)")
}
}
그럼 아래와 같이 정렬이 되구여, 좌우 스크롤이 가능합니다

- LazyHGrid의 초기화 값은 다음과 같습니다!
init(
rows: [GridItem],
alignment: VerticalAlignment = .center,
spacing: CGFloat? = nil,
pinnedViews: PinnedScrollableViews = .init(),
@ViewBuilder content: () -> Content
)
LazyVGrid
VGrid도 위에서 설명한 방식과 거의 유사해서 간단하게 설명하겠습니다.
LazyVGrid 는 수직으로 나타나기 때문에 ScrollView()에 .horizontal 를 빼주었습니다.
struct GridTest: View {
let columns = [GridItem(.fixed(30)), GridItem(.fixed(30))]
var body: some View {
ScrollView() {
LazyVGrid(columns: rows, spacing: 20) {
ForEach(1...30, id: \.self) { value in
Text("\(value)")
}
}
.padding(.horizontal)
}
}
}
- LazyVGrid의 초기화 값은 다음과 같습니다!
init(
columns: [GridItem],
alignment: VerticalAlignment = .center,
spacing: CGFloat? = nil,
pinnedViews: PinnedScrollableViews = .init(),
@ViewBuilder content: () -> Content
)
(H, VGrid의 차이는 row, colnums 밖에 없는 듯합니다!)
GridItem
- 그리드들의 항목을 구성하기 위해서 사용합니다!
- 아이템들은 열이나 행의 크기, 간격 등 레이아웃의 속성을 지정할 수 있습니다!
struct GridTest: View {
let column: [GridItem] = [
GridItem(.fixed(50), spacing: 10, alignment: nil),
GridItem(.fixed(100), spacing: 40, alignment: nil),
GridItem(.fixed(150), spacing: 0, alignment: nil)
]
var body: some View {
ScrollView() {
LazyVGrid(columns: column,alignment: .center, spacing: 50) {
ForEach(1...30, id: \.self) { value in
RoundedRectangle(cornerRadius: 10)
.fill(.blue)
.frame(height: 150)
Rectangle()
.fill(.green)
Capsule()
.fill(.brown)
}
}
.padding(.horizontal)
}
}
}

저도 공부하다가 봤는데 저렇게 열(column)별로 레이아웃을 다르게 할 수 있다는 걸 처음 알았네요
- GridItem의 초기화 값은 다음과 같습니다!.
init(
_ size: GridItem.Size = .flexible(),
spacing: CGFloat? = nil,
alignment: Alignment? = nil
)
여기서 size는 GridItem.Size 잖아여? 근데 이 Size가 enum으로 정의되어 있더라구여

여기서 Size의 case는 다음과 같이 총 3가지가 있습니다!!.
case adaptive(minimum: CGFloat, maximum: CGFloat = .infinity)
case fixed(CGFloat)
case flexible(minimum: CGFloat = 10, maximum: CGFloat = .infinity)
- adaptive - 이것도 항목을 유동적으로 조절함, 최소값 필수!
- 근데 사실 그럼 flexible 쓰면 되는거 아닌가? 왜 필요한지 잘 모르게씀
- fixed - 말 그대로 지정한 고정 크기를 할당합니다!
- flexible - 행 또는 열의 개수에 맞춰 뷰를 꽉 채웁니다! 최대, 최소값 지정 가능(필수 아님)
딴건 뭐 대충 알겠는데 pinnedViews 얘는 뭔가요???? (진짜모름)
스크롤 뷰의 경계에 고정을 시켜줄 수 있는 뷰 타입 집합이라고 합니다… (몬 소리임?)
struct PinnedScrollableViews 와 같이 선언되어 있구여
사실 말로 봐도 잘 이해가 안가더라구여 그래도 일단 보긴 해야하니까…
그리고 저 친구는
static let sectionHeaders: PinnedScrollableViews
static let sectionFooters: PinnedScrollableViews
이렇게 두 값을 가지고 있습니다.
경계에 고정시킬 수 있다하고, 헤더와 푸터옵션을 가진 걸 보니까 경계값을 나타낼때 쓰나봐요
요걸 사용하려면 일단 Section 으로 뷰가 구성되있어야 합니다!
struct GridTest: View {
let rows: [GridItem] = [
GridItem(.flexible(), spacing: nil, alignment: nil),
GridItem(.flexible(), spacing: nil, alignment: nil),
GridItem(.flexible(), spacing: nil, alignment: nil)
]
var body: some View {
ScrollView() {
LazyVGrid(columns: rows,alignment: .center, spacing: 6) {
Section(header: Text("section1")
.font(.largeTitle)) {
ForEach(1...30, id: \.self) { value in
Rectangle()
.fill(.blue)
.frame(height: 100)
.padding()
}
}
}
.padding(.horizontal)
}
}
}
다음과 같은 코드의 결과는 어떻게 될까여?
section의 header가 보이지만 스크롤을 좀만 내리면 저렇게 사라져 버립니다!!

이럴때 pinnedViews 를 사용하면!!!
pinnedViews: .sectionHeaders 를 그리드 초기화 부분에 추가시켜 줍니다!

그럼 GridItem에 있는 spacing이랑 Grid 초기화 구문에 있는 Spacing은 뭔 차이야?
struct GridTest: View {
let rows: [GridItem] = [
GridItem(.flexible(), spacing: 1, alignment: nil),
GridItem(.flexible(), spacing: 10, alignment: nil),
GridItem(.flexible(), spacing: 0, alignment: nil)
]
var body: some View {
ScrollView() {
LazyVGrid(columns: rows,alignment: .center, spacing: nil) {
ForEach(1...30, id: \.self) { value in
RoundedRectangle(cornerRadius: 10)
.fill(.blue)
.frame(height: 150)
}
}
.padding(.horizontal)
}
}
}

struct GridTest: View {
let rows: [GridItem] = [
GridItem(.flexible(), spacing: 1, alignment: nil),
GridItem(.flexible(), spacing: 1, alignment: nil),
GridItem(.flexible(), spacing: 0, alignment: nil)
]
var body: some View {
ScrollView() {
LazyVGrid(columns: rows,alignment: .center, spacing: 50) {
ForEach(1...30, id: \\.self) { value in
RoundedRectangle(cornerRadius: 10)
.fill(.blue)
.frame(height: 150)
}
}
.padding(.horizontal)
}
}
}

'iOS > SwiftUI' 카테고리의 다른 글
SwiftUI 내부 동작 원리 (0) | 2023.12.11 |
---|---|
SwiftUI 뷰의 변화 감지 (0) | 2023.07.09 |
SwiftUi DataBinding (0) | 2023.06.26 |