Devlog
article thumbnail

위 글은 유튜브 정대리님의 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)
                

 


                    

좌) 적용 전, 우) 적용 후 

 

 

profile

Devlog

@덩이

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그