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