apple/SwiftUI & Combine

[SwiftUI] LazyVGrid

lgvv 2022. 5. 25. 17:20

LazyVGrid

 

SwiftUI에 대해서 알아가고 있는데, UIKit에 비해서는 아직 어렵다.

UIKit이라면 금방 했을탠데, 아직까지는 숙련도가 낮은 것 같아서 어렵다. 적응하면 쉬워지겠지

 

iOS 14 혹은 15를 타겟으로 개발하고 있는데 SwiftUI가 80프로까지는 금방 만드는데, 결국 UIKit을 사용해야하는 시점에서는 점점 손이 많이가기 시작한다.

SwiftUI가 시간이 흐르면서 더 발전하겠지

 

✅ 코드

import Foundation
import SwiftUI

enum LayoutType: CaseIterable {
    case table, grid, multiple
}

extension LayoutType {
    // 레이아웃 타입에 대한 컬럼이 자동으로 설정되도록 한다
    var columns : [GridItem] {
        switch self {
        case .table:
            return [
                // flexible 하나로 한줄로 표현
                GridItem(.flexible())
            ]
        case .grid:
            return [
                // flexible 두개를 넣어서 두개 아이템 들어가게 함
                GridItem(.flexible()),
                GridItem(.flexible())
            ]
        case .multiple:
            return [
                // 어답티브를 통해 크기 닿는데 까지 아이템 여러개 넣기
                GridItem(.adaptive(minimum: 100))
            ]
        }
    }
}

struct SegmentLayoutView: View {
    
    var dummyDatas = MyModel.dummyDataArray
    
    @State var selectedLayoutType: LayoutType = .table
    
    var body: some View{
        VStack{
            // 피커
            Picker(selection: $selectedLayoutType, label: Text("레이아웃 타입"), content: /*@START_MENU_TOKEN@*/{
                ForEach(LayoutType.allCases, id: \.self , content: { layoutType in
                    switch layoutType {
                    case .table:
                        Image(systemName: "list.dash")
                    case .grid:
                        Image(systemName: "square.grid.2x2.fill")
                    case .multiple:
                        Image(systemName: "circle.grid.3x3.fill")
                    }
                })
            }/*@END_MENU_TOKEN@*/)
            .frame(width: 250)
            .pickerStyle(SegmentedPickerStyle())
            // 내용물
            ScrollView{
                LazyVGrid(columns: selectedLayoutType.columns, content: /*@START_MENU_TOKEN@*/ {
                
                	// Contents쪽에 switch문 달아서 view전환
                    ForEach(dummyDatas) { dataItem in
                        switch selectedLayoutType {
                        case .table:
                            Card(icon: "book.fill", title: "책읽기", start: "1 PM", end: "3 PM", bgColor: Color.green)
                        case .grid:
                                RoundedRectangle(cornerRadius: 25.0)
                                    .foregroundColor(Color.init(#colorLiteral(red: 1, green: 0.5758225922, blue: 0.3784928128, alpha: 1)))
                                    .frame(height: 200)
                                    .overlay(
                                        VStack(spacing: 2){
                                            Circle().frame(height: 100)
                                                .foregroundColor(.yellow)
                                            Spacer().frame(height: 10)
                                            Text("\(dataItem.title)")
                                                .font(.system(size: 20))
                                                .fontWeight(.bold)
                                            Text("\(dataItem.content)")
                                        }
                                    )
                        case .multiple:
                            Rectangle()
                                .foregroundColor(.blue)
                                .frame(height: 100)
                        }
                    }
                    
                }/*@END_MENU_TOKEN@*/)
                .animation(.easeInOut) // 효과 달아주기
                .padding(.horizontal, 10)
            }
        }
    }
}

 

 

 

결과물 UI

 

 

 

✅ 내가 직접 구현해보자

import SwiftUI

enum LayoutType: CaseIterable {
    case table, grid, multiple
    
    var columns: [GridItem] {
        switch self {
        case .table:
            return [GridItem(.flexible())]
        case .grid:
            return [
                GridItem(.flexible()),
                GridItem(.flexible())
            ]
        case .multiple:
            return [GridItem(.adaptive(minimum: 100))]
        }
    }
}

struct HomeView: View {
    
    @State var selectedLayoutType: LayoutType = .table
    
    var body: some View {
        VStack(spacing: 0) {
            Picker("", selection: $selectedLayoutType) { // picker를 스위치문으로 관리
                ForEach(LayoutType.allCases, id: \.self) {
                    switch $0 {
                    case .table: Image(systemName: "list.dash")
                    case .grid: Image(systemName: "square.grid.2x2.fill")
                    case .multiple: Image(systemName: "circle.grid.3x3.fill")
                    }
                }
                
            }
            .pickerStyle(.segmented)
            .padding()
            
            Spacer()
            
            ScrollView {
                LazyVGrid(
                    columns: selectedLayoutType.columns,
                    spacing: 5
                ) {
                    ForEach((0...30), id: \.self) { index in
                        switch selectedLayoutType { // 스위치문!
                        case .table:
                            RoundedRectangle(cornerRadius: 25.0)
                                .frame(height: 100)
                                .foregroundColor(.blue)
                                .padding([.leading, .trailing], 10)
                        case .grid:
                            RoundedRectangle(cornerRadius: 25.0)
                                .frame(height: 200)
                                .foregroundColor(.blue)
                                .overlay(
                                    VStack(spacing: 2){
                                        Circle()
                                            .frame(height: 100)
                                            .foregroundColor(.yellow)
                                        Spacer().frame(height: 10)
                                        Text("\(index)")
                                            .font(.system(size: 20))
                                            .fontWeight(.bold)
                                        Text("\(index)")
                                    }
                                )
                            
                        case .multiple:
                            Rectangle()
                                .foregroundColor(.blue)
                                .frame(height: 100)
                            
                            
                        }
                    }
                }
                .animation(.easeInOut)
                .padding(.horizontal, 10)
            }
            
            Spacer()
        }
    }
    
    
}

struct HalfSheet_Previews: PreviewProvider {
    static var previews: some View {
        HomeView()
    }
}



extension Color {
    static func random() -> Color {
        let random = Double(CGFloat(arc4random()) / CGFloat(UInt32.max))
        return Color(
            red:   random,
            green: random,
            blue:  random
        )
    }
}