SwiftUI로 위와같은 UI기능을 만드려고 하면서 알게 된
Namespace에 대해 간단하게 정리해보려고해요
먼저 개념을 둘러보면
프로퍼티를 포함하는 객체(뷰)의 영구 id로 정의된 네임스페이스에 접근할 수 있는 동적 속성 타입
객체의 정보를 id로 다른 뷰와 공유할 수 있는거에요
이 속성과 같이 사용하는게
View.matchedGeometryEffect(id: in:) 함수구요
동일한 키를 가진 다른 뷰가 새로운 뷰를 삽입하는 경우
시스템은 이전 위치에서 새로운 위치로 이동하는 하나의 뷰처럼 보이도록
window공간에 frame 사각형을 합칩니다.
일반적인 전환 메커니즘은 전환중 두 뷰가 각각 렌더링 되는 방식을 정의하며,
뷰의 렌더링이아닌 연결될 geometry에만 정렬합니다.
사용은 간단해요
상단탭바같이 사용하기위해 구현하려다보니 스유로는 잘 생각이안나더라구요
어느 하이라키에 저 언더바를 넣어야할지 부터 어떻게 위치를 잡아야할지...
막막하더라구요
먼저 각 버튼을 HStack에 담아서 탭바버튼을 만들거에요
그리고 각각 버튼안에 언더바(검정선)을 넣어줄거에요
struct TabBarView: View {
@Binding var currentTab: Int
var tabBarOptions: [String] = ["hello", "world", "this", "is", "something"]
var body: some View {
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 20) {
ForEach(tabBarOptions.indices, id: \.self) { index in
let title = tabBarOptions[index]
TabBarItem(currentTab: $currentTab,
title: title,
tab: index)
}
}
.padding(.horizontal)
}
.background(Color.white)
.frame(height: 40)
}
}
struct TabBarItem: View {
@Binding var currentTab: Int
var title: String
var tab: Int
var body: some View {
Button {
currentTab = tab
} label: {
VStack {
Spacer()
Text(title)
if currentTab == tab {
Color.black
.frame(height: 2)
} else {
Color.clear.frame(height: 2)
}
}
.animation(.spring(), value: currentTab)
}
.buttonStyle(.plain)
}
}
현 상태로는 버튼을 클릭하면 이렇게 버튼안에있는 버튼이 켜졋다 꺼졋다 하죠
이것을 이제
@Namespace를 사용하면
스르르륵 움직이게 할 수 있어요!!
위의 코드를 조금 손봐야해요
우선 모든 버튼의 Namespace를 같게해줘야해요
struct TabBarView: View {
@Binding var currentTab: Int
@Namespace var namespace << 추가된 부분
var tabBarOptions: [String] = ["hello", "world", "this", "is", "something"]
var body: some View {
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 20) {
ForEach(tabBarOptions.indices, id: \.self) { index in
let title = tabBarOptions[index]
TabBarItem(currentTab: $currentTab,
namespace: namespace, << 추가된 부분
title: title,
tab: index)
}
}
.padding(.horizontal)
}
.background(Color.white)
.frame(height: 40)
}
}
struct TabBarItem: View {
@Binding var currentTab: Int
let namespace: Namespace.ID << 추가된 부분
var title: String
var tab: Int
var body: some View {
Button {
currentTab = tab
} label: {
VStack {
Spacer()
Text(title)
if currentTab == tab {
Color.black
.frame(height: 2)
.matchedGeometryEffect(id: "underline", << 추가된 부분
in: namespace.self)
} else {
Color.clear.frame(height: 2)
}
}
.animation(.spring(), value: currentTab)
}
.buttonStyle(.plain)
}
}
탭바에서 Namespace를 만들어서
각 버튼을 그 Namespace.ID를 받아생성해요
그런 뒤
View.matchedGeometryEffect
를 이용해서 애니메이션을 처리해주면
서로 다른 뷰이지만 뷰에 대한 정보가 공유되서 같은뷰처럼 취급되고
애니메이션이 어디로 이동할지 결과를 알고있어요
따라서
눌려진 버튼에있는 언더바가 히든되고 누른 버튼에 있는 언더바가 보인다
->
눌려진 버튼의 언더바가 누른버튼 언더바로 이동한다
처럼
언더바가 깜박이는게아니라
누른 버튼으로 슬라이드되서 원하는 동작을 만들 수 있죠
'iyOmSd > Title: SwiftUI' 카테고리의 다른 글
[SwiftUI] ScrollView Offset (1) | 2022.09.07 |
---|---|
[SwiftUI] Animation과 Transition (0) | 2022.08.19 |
[SwiftUI] Button CornerRadius 효과주기 border, stroke, strokeBorder (0) | 2022.02.26 |
[SwiftUI] Localization 다국어 적용하기 (1) | 2022.02.10 |
[SwiftUI] SwiftUI Stanford 정리 (2) | 2022.01.26 |