위 글은 유튜브 정대리님의 SwiftUI fundamental Tutorial 강좌를 보고 작성한 정리글로
자세한 내용은 유튜브를 통해 확인하시길 권장합니다.
앞 시간에 생성한 MyView를 MyCustomView에 불러오기
import SwiftUI
enum TabIndex {
    case home, profile, cart
}
struct MyCustomView: View{
    
    @State
    var tabIndex : TabIndex
    
    var body: some View{
        
        GeometryReader{ geometry in
            ZStack{
                MyView(title: "home", bgColor: Color.green)
                
            }
            
        }
        .edgesIgnoringSafeArea(.all)
        
    }
}

import SwiftUI
enum TabIndex {
    case home, profile, cart
}
struct MyCustomView: View{
    
    @State
    var tabIndex : TabIndex
    
    func changeView(tabIndex: TabIndex) -> MyView{
        switch tabIndex {
        case .home:
            return MyView(title: "home", bgColor: Color.green)
        case .cart:
            return MyView(title: "cart", bgColor: Color.purple)
        case .profile:
            return MyView(title: "profile", bgColor: Color.blue)
            
        default:
            return MyView(title: "home", bgColor: Color.green)
        }
    }
    
    var body: some View{
        
        GeometryReader{ geometry in
            ZStack{
                
                self.changeView(tabIndex: self.tabIndex)
                
                HStack{
                    Button(action: {
                        print("home 클릭")
                    }){
                        Circle() //하단 버튼 효과를 내기 위함
                            .frame(width: geometry.size.width/3, height: 50)
                    }
                    Button(action: {
                        print("cart 클릭")
                    }){
                        
                    }
                    Button(action: {
                        print("profile 클릭")
                    }){
                        
                    }
                }
                
            }
            
        }
        .edgesIgnoringSafeArea(.all)
        
    }
}TabIndex를 매개변수로 갖는 함수 생성:  MyView를 반환함
    func changeView(tabIndex: TabIndex) -> MyView{
        switch tabIndex {
        case .home:
            return MyView(title: "home", bgColor: Color.green)
        case .cart:
            return MyView(title: "cart", bgColor: Color.purple)
        case .profile:
            return MyView(title: "profile", bgColor: Color.blue)
            
        default:
            return MyView(title: "home", bgColor: Color.green)
        }
    }
함수 호출 알아서 해당 뷰를 반환함)
               
self.changeView(tabIndex: self.tabIndex)
MyCustomView 안에서 부르기 때문에 self로 지칭

import SwiftUI
enum TabIndex {
    case home, profile, cart
}
struct MyCustomView: View{
    
    @State
    var tabIndex : TabIndex
    
    func changeView(tabIndex: TabIndex) -> MyView{
        switch tabIndex {
        case .home:
            return MyView(title: "home", bgColor: Color.green)
        case .cart:
            return MyView(title: "cart", bgColor: Color.purple)
        case .profile:
            return MyView(title: "profile", bgColor: Color.blue)
            
        default:
            return MyView(title: "home", bgColor: Color.green)
        }
    }
    
    var body: some View{
        
        GeometryReader{ geometry in
            ZStack(alignment:.bottom){
                
                self.changeView(tabIndex: self.tabIndex)
                
                HStack{
                    Button(action: {
                        print("home 클릭")
                    }){
                        Circle()
                            .frame(width: geometry.size.width/3, height: 50)
                    }
                    Button(action: {
                        print("cart 클릭")
                    }){
                        Circle()
                            .frame(width: geometry.size.width/3, height: 50)
                    }
                    Button(action: {
                        print("profile 클릭")
                    }){
                        Circle()
                            .frame(width: geometry.size.width/3, height: 50)
                    }
                }
                
            }
            
        }
        .edgesIgnoringSafeArea(.all)
        
    }
}stack들은 기본적으로 spacing을 가지고 있으므로 버튼 효과 원들이 각기 떨어져서 배치됨 (HStack)

HStack spacing: 0 처리
버튼 효과 조건문 주기: 디폴트 회색, 클릭시 버튼 이미지가 파란색으로 변함
import SwiftUI
enum TabIndex {
    case home, profile, cart
}
struct MyCustomView: View{
    
    @State
    var tabIndex : TabIndex
    
    func changeView(tabIndex: TabIndex) -> MyView{
        switch tabIndex {
        case .home:
            return MyView(title: "home", bgColor: Color.green)
        case .cart:
            return MyView(title: "cart", bgColor: Color.purple)
        case .profile:
            return MyView(title: "profile", bgColor: Color.blue)
            
        default:
            return MyView(title: "home", bgColor: Color.green)
        }
    }
    
    var body: some View{
        
        GeometryReader{ geometry in
            ZStack(alignment:.bottom){
                
                self.changeView(tabIndex: self.tabIndex)
                
                HStack(spacing:0){
                    Button(action: {
                        print("home 클릭")
                        self.tabIndex = .home
                    }){
                        Image(systemName: "house.fill")
                            .font(.system(size: 25))
                            .foregroundColor(self.tabIndex == .home ? Color.blue : Color.gray)
                            .frame(width: geometry.size.width/3, height: 50)
                    }.background(Color.white)
                    Button(action: {
                        print("cart 클릭")
                        self.tabIndex = .cart
                    }){
                        Image(systemName: "cart.fill")
                            .font(.system(size: 25))
                            .foregroundColor(self.tabIndex == .cart ? Color.blue : Color.gray)
                            .frame(width: geometry.size.width/3, height: 50)
                    }.background(Color.yellow)
                    Button(action: {
                        print("profile 클릭")
                        self.tabIndex = .profile
                    }){
                        Image(systemName: "person.circle.fill")
                            .font(.system(size: 25))
                            .foregroundColor(self.tabIndex == .profile ? Color.blue : Color.gray)
                            .frame(width: geometry.size.width/3, height: 50)
                    }.background(Color.orange)
                }
                
            }
            
        }
        .edgesIgnoringSafeArea(.all)
        
    }
}Image(systemName: "house.fill")
                            .font(.system(size: 25))
                            .foregroundColor(self.tabIndex == .home ? Color.blue : Color.gray) //조건문
                            .frame(width: geometry.size.width/3, height: 50)

버튼 클릭시 뷰 색상으로 버튼 색상 바꾸기
import SwiftUI
enum TabIndex {
    case home, profile, cart
}
struct MyCustomView: View{
    
    @State
    var tabIndex : TabIndex
    
    func changeView(tabIndex: TabIndex) -> MyView{
        switch tabIndex {
        case .home:
            return MyView(title: "home", bgColor: Color.green)
        case .cart:
            return MyView(title: "cart", bgColor: Color.purple)
        case .profile:
            return MyView(title: "profile", bgColor: Color.blue)
            
        default:
            return MyView(title: "home", bgColor: Color.green)
        }
    }
    
    func changeIcon(tabIndex: TabIndex) -> Color{
        switch tabIndex {
        case .home:
            return Color.green
        case .cart:
            return Color.purple
        case .profile:
            return Color.blue
            
        default:
            return Color.green
        }
    }
    
    var body: some View{
        
        GeometryReader{ geometry in
            ZStack(alignment:.bottom){
               
                self.changeView(tabIndex: self.tabIndex)
                
                HStack(spacing:0){
                    Button(action: {
                        print("home 클릭")
                        self.tabIndex = .home
                    }){
                        Image(systemName: "house.fill")
                            .font(.system(size: 25))
                            .foregroundColor(self.tabIndex == .home ? self.changeIcon(tabIndex: self.tabIndex): Color.gray)
                            .frame(width: geometry.size.width/3, height: 50)
                    }.background(Color.white)
                    Button(action: {
                        print("cart 클릭")
                        self.tabIndex = .cart
                    }){
                        Image(systemName: "cart.fill")
                            .font(.system(size: 25))
                            .foregroundColor(self.tabIndex == .cart ? self.changeIcon(tabIndex: self.tabIndex): Color.gray)
                            .frame(width: geometry.size.width/3, height: 50)
                    }.background(Color.yellow)
                    Button(action: {
                        print("profile 클릭")
                        self.tabIndex = .profile
                    }){
                        Image(systemName: "person.circle.fill")
                            .font(.system(size: 25))
                            .foregroundColor(self.tabIndex == .profile ? self.changeIcon(tabIndex: self.tabIndex): Color.gray)
                            .frame(width: geometry.size.width/3, height: 50)
                    }.background(Color.orange)
                }
                
            }
            
        }
        .edgesIgnoringSafeArea(.all)
        
    }
}함수로 만들어서 색상을 반환하도록 구현
func changeIcon(tabIndex: TabIndex) -> Color{
        switch tabIndex {
        case .home:
            return Color.green
        case .cart:
            return Color.purple
        case .profile:
            return Color.blue
            
        default:
            return Color.green
        }
    }
버튼 내 속성 조건문 설정
Image(systemName: "house.fill")
                            .font(.system(size: 25))
                            // 조건문: tabIndex가 해당되면 함수를 불러오기 
                            .foregroundColor(self.tabIndex == .home ? self.changeIcon(tabIndex: self.tabIndex): Color.gray)                            .frame(width: geometry.size.width/3, height: 50)
                    }.background(Color.white)

버튼 클릭시 아이콘이 커지도록 설정
import SwiftUI
enum TabIndex {
    case home, profile, cart
}
struct MyCustomView: View{
    
    @State
    var tabIndex : TabIndex
    
    @State
    var largerScale : CGFloat = 1.4
    
    func changeView(tabIndex: TabIndex) -> MyView{
        switch tabIndex {
        case .home:
            return MyView(title: "home", bgColor: Color.green)
        case .cart:
            return MyView(title: "cart", bgColor: Color.purple)
        case .profile:
            return MyView(title: "profile", bgColor: Color.blue)
            
        default:
            return MyView(title: "home", bgColor: Color.green)
        }
    }
    
    func changeIcon(tabIndex: TabIndex) -> Color{
        switch tabIndex {
        case .home:
            return Color.green
        case .cart:
            return Color.purple
        case .profile:
            return Color.blue
            
        default:
            return Color.green
        }
    }
    
    var body: some View{
        
        GeometryReader{ geometry in
            ZStack(alignment:.bottom){
               
                self.changeView(tabIndex: self.tabIndex)
                
                HStack(spacing:0){
                    Button(action: {
                        print("home 클릭")
                        self.tabIndex = .home
                    }){
                        Image(systemName: "house.fill")
                            .font(.system(size: 25))
                            .scaleEffect(self.tabIndex == .home ? self.largerScale : 1.0)
                            .foregroundColor(self.tabIndex == .home ? self.changeIcon(tabIndex: self.tabIndex): Color.gray)
                            .frame(width: geometry.size.width/3, height: 50)
                    }.background(Color.white)
                    Button(action: {
                        print("cart 클릭")
                        self.tabIndex = .cart
                    }){
                        Image(systemName: "cart.fill")
                            .font(.system(size: 25))
                            .scaleEffect(self.tabIndex == .cart ? self.largerScale : 1.0)
                            .foregroundColor(self.tabIndex == .cart ? self.changeIcon(tabIndex: self.tabIndex): Color.gray)
                            .frame(width: geometry.size.width/3, height: 50)
                    }.background(Color.yellow)
                    Button(action: {
                        print("profile 클릭")
                        self.tabIndex = .profile
                    }){
                        Image(systemName: "person.circle.fill")
                            .font(.system(size: 25))
                            .scaleEffect(self.tabIndex == .profile ? self.largerScale : 1.0)
                            .foregroundColor(self.tabIndex == .profile ? self.changeIcon(tabIndex: self.tabIndex): Color.gray)
                            .frame(width: geometry.size.width/3, height: 50)
                    }.background(Color.orange)
                }
                
            }
            
        }
        .edgesIgnoringSafeArea(.all)
        
    }
}State를 사용하여 변수 선언
@State
    var largerScale : CGFloat = 1.4
Image(systemName: "house.fill")
                            .font(.system(size: 25))
                            // 조건문: 디폴트 1.0배(크기 변화 없음), 해당 tabIndex면 아이콘 1.4배
                            .scaleEffect(self.tabIndex == .home ? self.largerScale : 1.0)
                            .foregroundColor(self.tabIndex == .home ? self.changeIcon(tabIndex: self.tabIndex): Color.gray)
                            .frame(width: geometry.size.width/3, height: 50)
                    }.background(Color.white)

import SwiftUI
enum TabIndex {
    case home, profile, cart
}
struct MyCustomView: View{
    
    @State
    var tabIndex : TabIndex
    
    @State
    var largerScale : CGFloat = 1.4
    
    func changeView(tabIndex: TabIndex) -> MyView{
        switch tabIndex {
        case .home:
            return MyView(title: "home", bgColor: Color.green)
        case .cart:
            return MyView(title: "cart", bgColor: Color.purple)
        case .profile:
            return MyView(title: "profile", bgColor: Color.blue)
            
        default:
            return MyView(title: "home", bgColor: Color.green)
        }
    }
    
    func changeIcon(tabIndex: TabIndex) -> Color{
        switch tabIndex {
        case .home:
            return Color.green
        case .cart:
            return Color.purple
        case .profile:
            return Color.blue
            
        default:
            return Color.green
        }
    }
    
    var body: some View{
        
        GeometryReader{ geometry in
            ZStack(alignment:.bottom){
                
                self.changeView(tabIndex: self.tabIndex)
                
                HStack(spacing:0){
                    Button(action: {
                        print("home 클릭")
                        
                        withAnimation{
                            self.tabIndex = .home
                        }
                    }){
                        Image(systemName: "house.fill")
                            .font(.system(size: 25))
                            .scaleEffect(self.tabIndex == .home ? self.largerScale : 1.0)
                            .foregroundColor(self.tabIndex == .home ? self.changeIcon(tabIndex: self.tabIndex): Color.gray)
                            .frame(width: geometry.size.width/3, height: 50)
                    }.background(Color.white)
                    Button(action: {
                        print("cart 클릭")
                        withAnimation{
                            self.tabIndex = .cart
                        }
                    }){
                        Image(systemName: "cart.fill")
                            .font(.system(size: 25))
                            .scaleEffect(self.tabIndex == .cart ? self.largerScale : 1.0)
                            .foregroundColor(self.tabIndex == .cart ? self.changeIcon(tabIndex: self.tabIndex): Color.gray)
                            .frame(width: geometry.size.width/3, height: 50)
                    }.background(Color.yellow)
                    Button(action: {
                        print("profile 클릭")
                        withAnimation{
                            self.tabIndex = .profile
                        }
                    }){
                        Image(systemName: "person.circle.fill")
                            .font(.system(size: 25))
                            .scaleEffect(self.tabIndex == .profile ? self.largerScale : 1.0)
                            .foregroundColor(self.tabIndex == .profile ? self.changeIcon(tabIndex: self.tabIndex): Color.gray)
                            .frame(width: geometry.size.width/3, height: 50)
                    }.background(Color.orange)
                }
                
            }
            
        }
        .edgesIgnoringSafeArea(.all)
        
    }
}Button(action: {
                        print("home 클릭")
                        
                        withAnimation{  // 버튼 클릭시 애니메이션 효과 주기
                            self.tabIndex = .home
                        }
                    }){
                        Image(systemName: "house.fill")
                            .font(.system(size: 25))
                            .scaleEffect(self.tabIndex == .home ? self.largerScale : 1.0)
                            .foregroundColor(self.tabIndex == .home ? self.changeIcon(tabIndex: self.tabIndex): Color.gray)
                            .frame(width: geometry.size.width/3, height: 50)
                    }.background(Color.white)

📌 문제 발생
애니메이션 효과로 인해 관련된 모든 뷰(위 코드에서는 MyView)에도 자체적으로 애니메이션 효과가 적용됨
관련된 뷰(MyView) 애니메이션 처리 없애기: ZStack에 animation(.none) 처리
import SwiftUI
struct MyView: View{
    
    var title: String
    
    var bgColor: Color
    
    var body: some View{
        
        ZStack{
            
            bgColor
//                .edgesIgnoringSafeArea(.all)
            
            Text(title)
                .font(.largeTitle)
                .fontWeight(.black)
                .foregroundColor(Color.white)
        }.animation(.none)
    }
}
TabView 뒤에 원을 그리고, 버튼을 클릭할 때 해당 버튼 뒤로 원의 위치 설정
import SwiftUI
enum TabIndex {
    case home, profile, cart
}
struct MyCustomView: View{
    
    @State
    var tabIndex : TabIndex
    
    @State
    var largerScale : CGFloat = 1.4
    
    func changeView(tabIndex: TabIndex) -> MyView{
        switch tabIndex {
        case .home:
            return MyView(title: "home", bgColor: Color.green)
        case .cart:
            return MyView(title: "cart", bgColor: Color.purple)
        case .profile:
            return MyView(title: "profile", bgColor: Color.blue)
            
        default:
            return MyView(title: "home", bgColor: Color.green)
        }
    }
    
    func changeIcon(tabIndex: TabIndex) -> Color{
        switch tabIndex {
        case .home:
            return Color.green
        case .cart:
            return Color.purple
        case .profile:
            return Color.blue
            
        default:
            return Color.green
        }
    }
   
    func circlePosition(tabIndex: TabIndex, geometry: GeometryProxy) -> CGFloat{
        switch tabIndex {
        case .home:
            return -(geometry.size.width / 3)
        case .cart:
            return 0
        case .profile:
            return geometry.size.width / 3
            
        default:
            return -(geometry.size.width / 3)
        }
    }
    
    var body: some View{
        
        GeometryReader{ geometry in
            ZStack(alignment:.bottom){
                
                self.changeView(tabIndex: self.tabIndex)
                
                Circle()
                    .frame(width: 90, height: 90)
                   
                    .offset(x: self.circlePosition(tabIndex: self.tabIndex, geometry: geometry), y: 12)
                
                HStack(spacing:0){
                    Button(action: {
                        print("home 클릭")
                        
                        withAnimation{
                            self.tabIndex = .home
                        }
                    }){
                        Image(systemName: "house.fill")
                            .font(.system(size: 25))
                            .scaleEffect(self.tabIndex == .home ? self.largerScale : 1.0)
                            .foregroundColor(self.tabIndex == .home ? self.changeIcon(tabIndex: self.tabIndex): Color.gray)
                            .frame(width: geometry.size.width/3, height: 50)
                    }.background(Color.white)
                    Button(action: {
                        print("cart 클릭")
                        withAnimation{
                            self.tabIndex = .cart
                        }
                    }){
                        Image(systemName: "cart.fill")
                            .font(.system(size: 25))
                            .scaleEffect(self.tabIndex == .cart ? self.largerScale : 1.0)
                            .foregroundColor(self.tabIndex == .cart ? self.changeIcon(tabIndex: self.tabIndex): Color.gray)
                            .frame(width: geometry.size.width/3, height: 50)
                    }.background(Color.yellow)
                    Button(action: {
                        print("profile 클릭")
                        withAnimation{
                            self.tabIndex = .profile
                        }
                    }){
                        Image(systemName: "person.circle.fill")
                            .font(.system(size: 25))
                            .scaleEffect(self.tabIndex == .profile ? self.largerScale : 1.0)
                            .foregroundColor(self.tabIndex == .profile ? self.changeIcon(tabIndex: self.tabIndex): Color.gray)
                            .frame(width: geometry.size.width/3, height: 50)
                    }.background(Color.orange)
                }
                
            }
            
        }
        .edgesIgnoringSafeArea(.all)
        
    }
}원의 위치를 해당 case별로 구분하기 위한 함수 생성
해당 버튼을 눌렀는지 확인하기 위함: TabIndex , geometry를 사용하기 위함: GeometryProxy
    func circlePosition(tabIndex: TabIndex, geometry: GeometryProxy) -> CGFloat{
        switch tabIndex {
        case .home:
            return -(geometry.size.width / 3) // 왼쪽
        case .cart:
            return 0 // 중간
        case .profile:
            return geometry.size.width / 3 // 오른쪽 
            
        default:
            return -(geometry.size.width / 3)
        }
    }
    
원을 그리고 .offset을 이용하여 디바이스에 따른 원 위치 계산
Circle()
                    .frame(width: 90, height: 90)
                    .offset(x: self.circlePosition(tabIndex: self.tabIndex, geometry: geometry), y: 12)
                

📌 참고: 작업하는 와중에 위와 같은 에러 발생함
출처: https://velog.io/@qkr0677/extra-tokens-at-the-end-of-sourceLocation-directive
extra tokens at the end of #sourceLocation directive
XCode의 자잘한 에러들
velog.io
원이 밑으로 치우쳐진 듯해서 위로 올리고 원과 버튼의 색상을 통일 시킴
import SwiftUI
enum TabIndex {
    case home, profile, cart
}
struct MyCustomView: View{
    
    @State
    var tabIndex : TabIndex
    
    @State
    var largerScale : CGFloat = 1.4
    
    func changeView(tabIndex: TabIndex) -> MyView{
        switch tabIndex {
        case .home:
            return MyView(title: "home", bgColor: Color.green)
        case .cart:
            return MyView(title: "cart", bgColor: Color.purple)
        case .profile:
            return MyView(title: "profile", bgColor: Color.blue)
            
        default:
            return MyView(title: "home", bgColor: Color.green)
        }
    }
    
    func changeIcon(tabIndex: TabIndex) -> Color{
        switch tabIndex {
        case .home:
            return Color.green
        case .cart:
            return Color.purple
        case .profile:
            return Color.blue
            
        default:
            return Color.green
        }
    }
    
    func circlePosition(tabIndex: TabIndex, geometry: GeometryProxy) -> CGFloat{
        switch tabIndex {
        case .home:
            return -(geometry.size.width / 3)
        case .cart:
            return 0
        case .profile:
            return geometry.size.width / 3
            
        default:
            return -(geometry.size.width / 3)
        }
    }
    
    var body: some View{
        
        GeometryReader{ geometry in
            ZStack(alignment:.bottom){
                
                self.changeView(tabIndex: self.tabIndex)
                
                Circle()
                    .frame(width: 90, height: 90)
              		// y값을 12->15로 변경 
                    .offset(x: self.circlePosition(tabIndex: self.tabIndex, geometry: geometry), y: 15)
                    .foregroundColor(.white)
                
                HStack(spacing:0){
                    Button(action: {
                        print("home 클릭")
                        
                        withAnimation{
                            self.tabIndex = .home
                        }
                    }){
                        Image(systemName: "house.fill")
                            .font(.system(size: 25))
                            .scaleEffect(self.tabIndex == .home ? self.largerScale : 1.0)
                            .foregroundColor(self.tabIndex == .home ? self.changeIcon(tabIndex: self.tabIndex): Color.gray)
                            .frame(width: geometry.size.width/3, height: 50)
                    }.background(Color.white)
                    Button(action: {
                        print("cart 클릭")
                        withAnimation{
                            self.tabIndex = .cart
                        }
                    }){
                        Image(systemName: "cart.fill")
                            .font(.system(size: 25))
                            .scaleEffect(self.tabIndex == .cart ? self.largerScale : 1.0)
                            .foregroundColor(self.tabIndex == .cart ? self.changeIcon(tabIndex: self.tabIndex): Color.gray)
                            .frame(width: geometry.size.width/3, height: 50)
                    }.background(Color.white)
                    Button(action: {
                        print("profile 클릭")
                        withAnimation{
                            self.tabIndex = .profile
                        }
                    }){
                        Image(systemName: "person.circle.fill")
                            .font(.system(size: 25))
                            .scaleEffect(self.tabIndex == .profile ? self.largerScale : 1.0)
                            .foregroundColor(self.tabIndex == .profile ? self.changeIcon(tabIndex: self.tabIndex): Color.gray)
                            .frame(width: geometry.size.width/3, height: 50)
                    }.background(Color.white)
                }
                
            }
            
        }
        .edgesIgnoringSafeArea(.all)
        
    }
}
offset 추가로 아이콘을 위로 좀 올림
기종에 따른 frame(), Circle() 조건문 추가
import SwiftUI
enum TabIndex {
    case home, profile, cart
}
struct MyCustomView: View{
    
    @State
    var tabIndex : TabIndex
    
    @State
    var largerScale : CGFloat = 1.4
    
    func changeView(tabIndex: TabIndex) -> MyView{
        switch tabIndex {
        case .home:
            return MyView(title: "home", bgColor: Color.green)
        case .cart:
            return MyView(title: "cart", bgColor: Color.purple)
        case .profile:
            return MyView(title: "profile", bgColor: Color.blue)
            
        default:
            return MyView(title: "home", bgColor: Color.green)
        }
    }
    
    func changeIcon(tabIndex: TabIndex) -> Color{
        switch tabIndex {
        case .home:
            return Color.green
        case .cart:
            return Color.purple
        case .profile:
            return Color.blue
            
        default:
            return Color.green
        }
    }
    
    func circlePosition(tabIndex: TabIndex, geometry: GeometryProxy) -> CGFloat{
        switch tabIndex {
        case .home:
            return -(geometry.size.width / 3)
        case .cart:
            return 0
        case .profile:
            return geometry.size.width / 3
            
        default:
            return -(geometry.size.width / 3)
        }
    }
    
    var body: some View{
        
        GeometryReader{ geometry in
            ZStack(alignment:.bottom){
                
                self.changeView(tabIndex: self.tabIndex)
                
                Circle()
                    .frame(width: 90, height: 90)
                    
                    .offset(x: self.circlePosition(tabIndex: self.tabIndex, geometry: geometry), y: UIApplication.shared.windows.first? .safeAreaInsets.bottom == 0 ? 20: 0)
                    .foregroundColor(.white)
                
                VStack(spacing: 0){
                
                HStack(spacing:0){
                    Button(action: {
                        print("home 클릭")
                        
                        withAnimation{
                            self.tabIndex = .home
                        }
                    }){
                        Image(systemName: "house.fill")
                            .font(.system(size: 25))
                            .scaleEffect(self.tabIndex == .home ? self.largerScale : 1.0)
                            .foregroundColor(self.tabIndex == .home ? self.changeIcon(tabIndex: self.tabIndex): Color.gray)
                            .frame(width: geometry.size.width/3, height: 50)
                            .offset(y: self.tabIndex == .home ? -10 : 0) // 아이콘 위로 올리기
                    }.background(Color.white)
                    Button(action: {
                        print("cart 클릭")
                        withAnimation{
                            self.tabIndex = .cart
                        }
                    }){
                        Image(systemName: "cart.fill")
                            .font(.system(size: 25))
                            .scaleEffect(self.tabIndex == .cart ? self.largerScale : 1.0)
                            .foregroundColor(self.tabIndex == .cart ? self.changeIcon(tabIndex: self.tabIndex): Color.gray)
                            .frame(width: geometry.size.width/3, height: 50)
                            .offset(y: self.tabIndex == .cart ? -10 : 0) // 아이콘 위로 올리기
                    }.background(Color.white)
                    Button(action: {
                        print("profile 클릭")
                        withAnimation{
                            self.tabIndex = .profile
                        }
                    }){
                        Image(systemName: "person.circle.fill")
                            .font(.system(size: 25))
                            .scaleEffect(self.tabIndex == .profile ? self.largerScale : 1.0)
                            .foregroundColor(self.tabIndex == .profile ? self.changeIcon(tabIndex: self.tabIndex): Color.gray)
                            .frame(width: geometry.size.width/3, height: 50)
                            .offset(y: self.tabIndex == .profile ? -10 : 0) // 아이콘 위로 올리기
                    }.background(Color.white)
                }
                Rectangle()
                    .foregroundColor(.white)
                    
                    .frame(height: UIApplication.shared.windows.first? .safeAreaInsets.bottom == 0 ? 0 : 20)
                    
            }
        }
        }
        .edgesIgnoringSafeArea(.all)
        
    }
}
훔 버튼이 있는 기종에 따라 frame으로 padding 효과를 주는 조건문 추가
홈 버튼이 있다면(UIApplication.shared.windows.first? .safeAreaInsets.bottom == 0) frame을 넣지 않고
홈 버튼이 없다면 frame을 20 넣어줌
Rectangle()
                    .foregroundColor(.white)
                    
                    .frame(height: UIApplication.shared.windows.first? .safeAreaInsets.bottom == 0 ? 0 : 20)
홈 버튼이 있다면(UIApplication.shared.windows.first? .safeAreaInsets.bottom == 0) 아이콘의 y값을 20을 넣어주고 (위로 올라가게끔 )
홈 버튼이 없다면 y값을 주지 않음
Circle()
                    .frame(width: 90, height: 90)
                    
                    .offset(x: self.circlePosition(tabIndex: self.tabIndex, geometry: geometry), y: UIApplication.shared.windows.first? .safeAreaInsets.bottom == 0 ? 20: 0)
                    .foregroundColor(.white)
                
                    


'강의 > etc' 카테고리의 다른 글
| [SwiftUI fundamental Tutorial] TextField, SecureField (0) | 2021.09.14 | 
|---|---|
| [SwiftUI fundamental Tutorial] ButtonStyle (0) | 2021.09.14 | 
| [SwiftUI fundamental Tutorial] TabView (0) | 2021.08.31 | 
| [SwiftUI fundamental Tutorial] GeometryReader (0) | 2021.08.31 | 
| [SwiftUI fundamental Tutorial] Navigation View (0) | 2021.08.25 |