반응형
Drawer (Side Menu)를 커스텀하게 작성하기 위해서는 기본적으로 아래와 같이 작성해서 기본 구조를 잡습니다.
struct DrawserWithTabView: View {
@State private var showDrawer: Bool = false
var body: some View {
HStack(spacing: 0) {
Drawer(showDrawer: $showDrawer)
TabView {
Text("Home")
}
.frame(width: UIScreen.main.bounds.width)
}
.frame(width: UIScreen.main.bounds.width)
.offset(x: 125)
}
}
struct Drawer: View {
@Binding var showDrawer: Bool
var body: some View {
VStack {
HStack {
Image(systemName: "person")
.resizable()
.frame(width: 50, height: 50)
Spacer()
}
.padding()
Spacer()
}
.frame(width: 250)
.background(
Color.black.opacity(0.5)
.ignoresSafeArea(.all, edges: .vertical)
)
}
}
Drawer (Side Menu)의 너비는 임의로 250으로 설정했습니다. 그리고 Drawer (Side Menu)가 표시될 때의 offset은 너비의 절반을 주었습니다.
그리고 Drawer (Side Menu)를 보여주고 사라지게 해줄 버튼(DrawerButton)을 만들어줍니다.
struct Drawer: View {
....
var body: some View {
VStack {
HStack {
Image(systemName: "person")
.resizable()
.frame(width: 50, height: 50)
Spacer()
DrawerButton(showDrawer: $showDrawer) // 추가
}
.padding()
Spacer()
}
....
}
}
struct DrawerButton: View {
@Binding var showDrawer: Bool
var body: some View {
Button {
withAnimation {
showDrawer.toggle()
}
} label: {
VStack(spacing: 5) {
Capsule()
.fill(Color.white)
.frame(width: 35, height: 3)
.rotationEffect(.init(degrees: showDrawer ? -50 : 0))
.offset(x: showDrawer ? 2 : 0, y: showDrawer ? 9 : 0)
VStack(spacing: 5) {
Capsule()
.fill(Color.white)
.frame(width: 35, height: 3)
Capsule()
.fill(Color.white)
.frame(width: 35, height: 3)
.offset(y: showDrawer ? -8 : 0)
}
.rotationEffect(.init(degrees: showDrawer ? 50 : 0))
}
.scaleEffect(0.8)
}
}
}
마지막으로 Drawer (Side Menu)가 표시되지 않을 때에는 Drawer Button만 표시되고 Drawer Button를 클릭하게 되면 Drawer (Side Menu)가 표시되면서 Drawer Button 위치를 이동시키도록 코드를 추가 및 변경해줍니다.
struct DrawserWithTabView: View {
....
@Namespace var animation
var body: some View {
HStack(spacing: 0) {
Drawer(showDrawer: $showDrawer, animation: animation)
....
}
.frame(width: UIScreen.main.bounds.width)
.offset(x: showDrawer ? 125 : -125)
.overlay(
ZStack {
if !showDrawer {
DrawerButton(showDrawer: $showDrawer, animation: animation)
.padding()
}
}, alignment: .topLeading
)
}
}
struct Drawer: View {
...
var animation: Namespace.ID
var body: some View {
VStack {
HStack {
...
if showDrawer {
DrawerButton(showDrawer: $showDrawer, animation: animation)
}
}
...
}
...
}
}
struct DrawerButton: View {
...
var animation: Namespace.ID
var body: some View {
Button {
...
} label: {
VStack(spacing: 5) {
Capsule()
.fill(showDrawer ? Color.white : Color.primary)
...
VStack(spacing: 5) {
Capsule()
.fill(showDrawer ? Color.white : Color.primary)
...
Capsule()
.fill(showDrawer ? Color.white : Color.primary)
...
}
...
}
...
.matchedGeometryEffect(id: "DRAWER_BUTTON", in: animation)
}
}
}
반응형
'Dev-iOS > UI' 카테고리의 다른 글
[UI] 스크롤 시 상단 탑 SearchBar 이동 시키기 - (SwiftUI 2.0 - iOS 14 이상) (0) | 2023.07.20 |
---|---|
[UI] pull to refresh - (SwiftUI 2.0 - iOS 14 이하) (0) | 2023.07.12 |
[UI] Drag & Drop - (SwiftUI 2.0 - iOS 14 이상) (0) | 2023.07.12 |
[UI] 상단 탭 화면 with Animation (SwiftUI 2.0 - iOS 14 이상) (0) | 2023.07.11 |
[UI] Carousel (SwiftUI 2.0 - iOS 14 이상) (0) | 2023.07.11 |