iOS/SwiftUI

[iOS/SwiftUI] LazyVGrid를 활용하여 뷰 만들기

yanni13 2024. 2. 25. 03:09

 

오늘은 핀터레스트에서 보던 메인 뷰처럼 구현하기 위해 swiftUI에서 사용하는 LazyVGrid를 활용하여 

뷰 구성을 해보겠다!

 

 

 

View

 

 

우선 내가 구성한 뷰는 이렇다

LazyVGrid가 뭐고 어떻게 쓰는건데!? 라고 할 수 있으니 간단한 설명을 해보겠다.

 

LazyVGrid?

VStack처럼 열(Columns) 기반의 그리드 레이아웃을 지연 로딩 방식으로 구현할 때 사용되는 컨테이너라고 한다.

즉, 2차원의 행이 형성되고 세로로 계속 스크롤 할 수 있는 게 특징이다.

 

 

flexible, adaptive

LazyVGrid를 사용할 때 GridItem을 만들때 만들 수 있는 형태가 3가지가 있다.

fixed, adaptive, flexible 총 3가지가 있지만, 그중 제일 많이 사용하는 adaptive와 flexible 두 가지에 대해 

간단하게 설명해보겠다.

 

flexible

flexible이란 아이템 사이즈가 유동적일 때, 즉 아이템 크기에 따라 그리드의 유형이 바뀔 때 사용하는 게 특징이다.

flexible로 구현을 하려면 최솟값, 최댓값을 지정해줘야 하며 열을 필수로 지정해줘야 한다.

 

나는 구현할 때 핀터레스트의 디자인을 최대한 참고해서 구현하려고 했기 때문에 flexible로 구현해 주었다.

let columns = [GridItem(.flexible(minimum: 10, maximum: .infinity))]

 

 

 

최댓값은 사진 크기에 맞게 늘릴 수 있는 최대만큼 늘어나길 원했기 때문에 infinity 속성을 넣어줬다.

 

 

adaptive

adaptive는 아이템 사이즈가 고정일 때 주로 사용한다.

유동적으로 디바이스 크기에 따라 자동적으로 늘릴 수 있으므로 columns를 따로 지정해주지 않아도 되는 게 특징이다.

 

 

구현 코드

 

우선 앞에 구현 사진을 보면 + 버튼을 통해 사진을 불러와 메인 보드에 띄우는 것까지는 실패했다. 

그 이유는 메인 뷰에서 사진 크기에 따라 동적으로 보이게 하고 싶기도 하고 시각적으로 예뻐 보이게 하기 위해서 

 1열(왼쪽 열)이랑 2열(오른쪽 열)의 그리드를 분리하여 배치하도록 하였다.

 

 

HStack(alignment: .top, spacing: -20) {
                        
                        VStack {
                            LazyVGrid(columns:columns, spacing: 10) {
                                ForEach(leftItems, id: \.title) { item in
                                    Image(item.title)
                                        .resizable()
                                        .aspectRatio(contentMode: .fit)
                                        .scaledToFit()
                                        .cornerRadius(10)
                                    
                                }
                                
                            }
                            .padding()
                            
                        }
                        
                        
                        VStack(spacing: 20.0) {
                            LazyVGrid(columns:columns, spacing: 10) {
                                ForEach(rightItems, id: \.title) { item in
                                    Image(item.title)
                                        .resizable()
                                        .aspectRatio(contentMode: .fit)
                                        .scaledToFit()
                                        .cornerRadius(10)
                                    
                                }
                            }
                            
                            .padding()
                            
                        }
                        
                        
                        .navigationBarTitle(Text("Pinterest"), displayMode: .inline)
                        .navigationBarItems(trailing:
                                                NavigationLink(destination: DetailView(boardData: boardData)) {
                            Image(systemName: "plus")
                                .foregroundColor(Color.red)
                                .font(.title)
                        })
                        
                    }

 

코드를 설명하자면 HStack에 두 개의 그리드를 나열해주어야 하기 때문에 HStack을 크게 감쌌고, 

그리드 내부에서는 수직 방향으로 행이 계속 추가가 돼야 하는 구조기 때문에 VStack으로 그리드를 감싸주었다.

 

Foreach문을 통해 미리 assets파일에 저장해 뒀던 이미지들을 순차적으로 불러왔다.

assets파일의 사진들을 호출하여 뷰에 띄우는 거까지 LazyVGrid를 잘 활용하였다.

 

 

 근데 여기서.. 사진을 추가하여 추가된 사진을 메인 뷰에서 확인하고자 할 때 문제가 된다.

 

내가 구현하고 싶었던 건 추가된 사진이 왼쪽 그리드, 오른쪽 그리드 랜덤하게 추가되길 원했다.

근데 그리드를 두 개로 쪼개놔서 이걸 어떻게 랜덤 하게 구현하느냐가 문제가 되었다..

거기서부터 머리가 꼬여버렸는데 ,, 차차 해결해 나가야겠다.

 

 

 

정처기 준비한다고 개발을 1주일이나 넘게 쉰 거 같은데 그새 처음 보는 코드 같고 익숙하던 문법들도 

새로 구현하려고 하니 기억이 가물가물했다..

 

 

영어단어마냥.. 하루도 쉬지 않고 해야 몸에 익는다는 걸 정말 몸소 느꼈다.

 

다음 블로그는 핀터레스트와 유사한 프로젝트 전체 코드와 위의 문제점을 해결한 방식을 포스팅 해야겠다

(꼭.. 제발)