본문 바로가기

iOS/SwiftUI

SwiftUI Grid

오늘 알아볼것은 SwiftUI에서 Grid입니다!!!

사실 지금까지 쓸 일이 없었고, 그냥 아 저런게 있구나 이렇게만 알고 있었거든여

근데 이번에 앱스쿨 과제를 만들때 한번 써볼까?? 싶어서 정리해봤습니다!! (

안하면 맨날 까먹어서 다시 찾아야함 ㅋㅋ

)

Grid

  • 컨테이너에 뷰를 2차원 정렬하는 레이아웃임!!

LazyHGrid


  • 수평으로 늘어나는 Grid임!!
  • 그래서 가로로 스크롤이 가능한 뷰 컬렉션을 표현할 때 사용함!!
    • 그래서 보통 ScrollView 랑 같이 쓰는거 같아여

사용하려면?

  1. 그리드에 포함될 열 항목의 배열을 생성해야 합니다.

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