위 글은 유튜브 정대리님의 SwiftUI fundamental Tutorial 강좌를 보고 작성한 정리글로
자세한 내용은 유튜브를 통해 확인하시길 권장합니다.
LazyVGrid란? 뷰를 화면에 보여줄 때 화면에 보이는 부분만 렌더링이 되는 기능
import SwiftUI
struct MyModel : Identifiable{
let id = UUID()
let title : String
let content : String
}
// 더미 데이터를 가져오도록 함
extension MyModel{
// MyModel에 대한 인스턴스를 생성하지 않아도 접근해서 가져올 수 있도록
static var dummyDataArray: [MyModel]{
(1...2000).map{ (number: Int) in
MyModel(title: "title: \(number)", content: "content: \(number)")
}
}
}
struct ContentView: View {
var dummyDataArray = MyModel.dummyDataArray
var body: some View {
ScrollView{ // 스크롤이 가능하도록 설정
LazyVGrid(columns: [
GridItem(.fixed(100))
], content: {
ForEach(dummyDataArray, content:{ (dataItem: MyModel) in
Rectangle().foregroundColor(.blue)
.frame(height: 120)
.overlay(Text("\(dataItem.title)"))
})
})
}
}
}
LazyVGrid: 레이지 버티칼 그리드 뷰
LazyVGrid(columns: Horizontal 아이템 레이아웃을 설정하는 부분, content)
GridItem 옵션 알아보기: fixed / adaptive / flexible
ScrollView{
// 그리드 아이템 옵션 3가지
LazyVGrid(columns: [
GridItem(.adaptive(minimum: 50)),
GridItem(.fixed(50)),
GridItem(.flexible(minimum: 50))
], content: {
ForEach(dummyDataArray, content:{ (dataItem: MyModel) in
Rectangle().foregroundColor(.blue)
.frame(height: 120)
.overlay(Text("\(dataItem.title)"))
})
})
}
1. .fixed: 고정 값
2. .adaptive: 최소 (n)만큼의 사이즈로 여러 개를 계산해서 분할로 채워줌
3. .flexible: 계산해서 하나만 채우기
LazyVGrid의 spacing 처리
ScrollView{
LazyVGrid(columns: [
GridItem(.adaptive(minimum: 50)),
GridItem(.fixed(50)),
GridItem(.flexible(minimum: 50))
], spacing: 100, content: {
ForEach(dummyDataArray, content:{ (dataItem: MyModel) in
Rectangle().foregroundColor(.blue)
.frame(height: 120)
.overlay(Text("\(dataItem.title)"))
})
})
}
spacing: 각 줄에 대한 spacing (default = 10)
기본 적용하기
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 [
GridItem(.flexible()),
GridItem(.flexible())
]
case .multiple:
return [
GridItem(.adaptive(minimum: 100))
]
}
}
}
struct lazyVGrid_apply: View {
@State var dummyData = MyModel.dummyDataArray
@State var selected: LayoutType = .table
var body: some View {
VStack{
Picker(selection: $selected, label: Text("LayoutType"), content: {
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")
}
})
}).pickerStyle(SegmentedPickerStyle())
//CONTENTS
ScrollView{
LazyVGrid(columns: selected.columns, content: {
ForEach(dummyData){ dataItem in
Rectangle()
.foregroundColor(.blue)
.frame(height: 100)
}
})
}
}
}
}
1. LayoutType을 ForEach로 돌리려면 CaseIterable를 해줘야 함
이는 case를 collection으로 제공한다는 의미
enum LayoutType : CaseIterable{
case table, grid, multiple
}
LayoutType.allCases: LayoutType이 가지고 있는 모든 케이스들이 반복해서 들어옴
VStack{
Picker(selection: $selected, label: Text("LayoutType"), content: {
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")
}
})
}).pickerStyle(SegmentedPickerStyle())
2. LayoutType 자체를 extension하기
extension LayoutType{
var columns : [GridItem]{ // LayoutType에 대한 columns이 자동으로 설정되도록 함
switch self {
case .table:
return [
//flexible 하나로 한줄로 표현
GridItem(.flexible())
]
case .grid:
return [
// flexible 두개를 넣어서 두개의( 아이템을 들어가게 )레이아웃 표현
GridItem(.flexible()),
GridItem(.flexible())
]
case .multiple:
return [
// adaptive를 통해 크기를 닿는데까지 아이템을 여러개 넣기
GridItem(.adaptive(minimum: 100))
]
}
}
}
LazyVGrid에 애니메이션 효과 주기: LazyVGrid 자체적으로 제공 함
ScrollView{
LazyVGrid(columns: selected.columns, content: {
ForEach(dummyData){ dataItem in
Rectangle()
.foregroundColor(.blue)
.frame(height: 100)
}
}).animation(.easeIn/.easeInOut)
}
Picker의 select value 값에 따라 CONTENTS 바꾸기
import SwiftUI
enum LayoutType : CaseIterable{
case table, grid, multiple
}
extension LayoutType{
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 lazyVGrid_apply: View {
@State var dummyData = MyModel.dummyDataArray
@State var selected: LayoutType = .table
var body: some View {
VStack{
Picker(selection: $selected, label: Text("LayoutType"), content: {
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")
}
})
})
.frame(width: 250)
.pickerStyle(SegmentedPickerStyle())
//CONTENTS
ScrollView{
LazyVGrid(columns: selected.columns, content: {
ForEach(dummyData){ dataItem in
switch selected{
case .table :
Rectangle()
.foregroundColor(.red)
.frame(height: 100)
case .grid:
Rectangle()
.foregroundColor(.blue)
.frame(height: 100)
case .multiple:
Rectangle()
.foregroundColor(.yellow)
.frame(height: 100)
}
}
})
.animation(.easeInOut)
.padding(.horizontal, 10)
}
}
}
}
View를 따로 만들어서 CONTENTS에 적용하기
import SwiftUI
struct MyTable : View{
var icon : String
var title : String
var start : String
var end : String
var color : Color
var body: some View{
HStack(spacing: 10){
Image(systemName: icon)
.font(.system(size: 40))
.foregroundColor(.white)
VStack(alignment: .leading, spacing: 0) {
Divider().opacity(0)
Text(title)
.fontWeight(.bold)
.font(.system(size: 23))
.foregroundColor(.white)
Spacer().frame(height:5)
Text("\(start)-\(end)")
.foregroundColor(.white)
}
}
.padding(20)
.background(color)
.cornerRadius(20)
}
}
struct MyTable_Previews: PreviewProvider{
static var previews: some View{
MyTable(icon: "book.fill", title: "공부하기", start: "아침에 눈 뜨고", end: "뒤지기 전까지", color: Color.blue)
}
}
import SwiftUI
enum LayoutType : CaseIterable{
case table, grid, multiple
}
extension LayoutType{
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 lazyVGrid_apply: View {
@State var dummyData = MyModel.dummyDataArray
@State var selected: LayoutType = .table
var body: some View {
VStack{
Picker(selection: $selected, label: Text("LayoutType"), content: {
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")
}
})
})
.frame(width: 250)
.pickerStyle(SegmentedPickerStyle())
//CONTENTS
ScrollView{
LazyVGrid(columns: selected.columns, content: {
ForEach(dummyData){ dataItem in
switch selected{
case .table :
MyTable(icon: "book.fill", title: "공부하기", start: "아침에 눈 뜨고", end: "뒤지기 전까지", color: Color.blue)
case .grid:
RoundedRectangle(cornerRadius: 25)
.foregroundColor(Color.init(#colorLiteral(red: 0.1764705926, green: 0.4980392158, blue: 0.7568627596, alpha: 1)))
.frame(height: 200)
.overlay(
VStack(spacing: 2){
Circle().frame(height: 100)
.foregroundColor(Color.init(#colorLiteral(red: 0.4745098054, green: 0.8392156959, blue: 0.9764705896, alpha: 1)))
Spacer().frame(height: 10)
Text("\(dataItem.title)")
.font(.system(size: 20))
.fontWeight(.bold)
Text("\(dataItem.content)")
}
)
case .multiple:
Rectangle()
.foregroundColor(Color.init(#colorLiteral(red: 0.2588235438, green: 0.7568627596, blue: 0.9686274529, alpha: 1)))
.frame(height: 100)
}
}
})
.animation(.easeInOut)
.padding(.horizontal, 10)
}
}
}
}
'강의 > etc' 카테고리의 다른 글
[JS] 2022 30분 요약 강좌(1) (0) | 2022.03.15 |
---|---|
[SwiftUI fundamental Tutorial] Redux (0) | 2021.10.16 |
[SwiftUI fundamental Tutorial] Menu (0) | 2021.10.07 |
[SwiftUI fundamental Tutorial] Deeplink (0) | 2021.10.06 |
[SwiftUI fundamental Tutorial] Picker, SegmentedStyle (0) | 2021.10.05 |