[SwiftUI] 사이드 메뉴 만들기
메뉴 호출
프로젝트를 시작하면 다음과 같은 메세지가 나옵니다.
struct ContentView: View {
var body: some View {
Text("Hello, world!")
.padding()
}
}
메뉴를 여는 버튼을 붙여 봅니다.
struct ContentView: View {
var body: some View {
MainView()
}
}
struct MainView: View {
var body: some View {
Button(action: {
print("Open the side menu")
}) {
Text("Show Menu")
}
}
}
MainView는 전체 화면이 필요 합니다.
전체 슈퍼 뷰의 높이와 너비를 알기 위해 MainView 를 GeometryReader로 래핑합니다.
struct ContentView: View {
var body: some View {
GeometryReader { geometry in
MainView()
}
}
}
화면이 전체를 사용하도록 변경 합니다.
struct ContentView: View {
var body: some View {
GeometryReader { geometry in
MainView()
.frame(width: geometry.size.width, height: geometry.size.height)
}
}
}
메뉴 디자인
이제 사이드 메뉴를 디자인하겠습니다.
새로운 File-New-File을 만들고, SwiftUI 보기를 만들고 그것을 MenuView 라고 부릅니다.
메뉴에는 세로로 배열된 4개의 메뉴 항목이 있어야 합니다.
이를 위해, 우리는 leading 정렬 모드 VStack를 사용 합니다.
struct MenuView: View {
var body: some View {
VStack(alignment: .leading) {
}
}
}
메뉴는 이미지와 텍스트로 만듭니다.
VStack(alignment: .leading) {
HStack {
}
}
아이콘을 넣어 줍니다.
이제 "사람"시스템 아이콘을 사용하여 회색으로 만들고 확대합니다.
VStack(alignment: .leading) {
HStack {
Image(systemName: "person")
.foregroundColor(.gray)
.imageScale(.large)
Text("Profile")
.foregroundColor(.gray)
.font(.headline)
}
}
3개 만듭니다.
VStack(alignment: .leading) {
HStack {
Image(systemName: "person")
.foregroundColor(.gray)
.imageScale(.large)
Text("Profile")
.foregroundColor(.gray)
.font(.headline)
}
.padding(.top, 100)
HStack {
Image(systemName: "envelope")
.foregroundColor(.gray)
.imageScale(.large)
Text("Messages")
.foregroundColor(.gray)
.font(.headline)
}
.padding(.top, 30)
HStack {
Image(systemName: "gear")
.foregroundColor(.gray)
.imageScale(.large)
Text("Settings")
.foregroundColor(.gray)
.font(.headline)
}
.padding(.top, 30)
}
마지막에 Spacer 를 사용해 위로 올립니다.
VStack(alignment: .leading) {
HStack {
//...
}
.padding(.top, 100)
HStack {
//...
}
.padding(.top, 30)
HStack {
//....
}
.padding(.top, 30)
Spacer()
}
ContentView에 MenuView 추가
MenuView 가 ContentView 내부에 표시되어야 하는지 여부를 추적하기 위해 다음과 같은 State를 선언합니다.
struct ContentView: View {
@State var showMenu = false
var body: some View {
//...
}
}
showMenu 상태가 true이면 MenuView가 MainView 상단에 표시되어야 하고 왼쪽에 정렬되어 있어야 합니다. 따라서 MainView를 ZStack으로 래핑 하고 State 값에 따라 MenuView를 삽입합니다 .
var body: some View {
GeometryReader { geometry in
ZStack(alignment: .leading) {
MainView()
.frame(width: geometry.size.width, height: geometry.size.height)
if self.showMenu {
MenuView()
}
}
}
}
메뉴는 화면의 절반만 덮어야 하므로 다음 .frame을 추가합니다 .
if self.showMenu {
MenuView()
.frame(width: geometry.size.width/2)
}
이제 MainView 에서 showMenu State 로 바인딩을 만들 수 있습니다 .
struct MainView: View {
@Binding var showMenu: Bool
var body: some View {
//...
}
}
ContentView 내에서 초기화합니다 .
MainView(showMenu: self.$showMenu)
.frame(width: geometry.size.width, height: geometry.size.height)
이제 MainView의 버튼을 사용 하여 Binding을 통해 showMenu 상태 를 토글할 수 있습니다. 그러면 ContentView 가 결국 MenuView를 표시하여 자체적으로 다시 빌드됩니다.
Button(action: {
self.showMenu = true
}) {
Text("Show Menu")
}
또한 사이드 메뉴가 열릴 때 MainView 를 오른쪽 으로 이동하려고 합니다 . 또한 메뉴가 다시 닫힐 때까지 MainView 의 모든 기능을 비활성화하려고 합니다.
MainView(showMenu: self.$showMenu)
.frame(width: geometry.size.width, height: geometry.size.height)
.offset(x: self.showMenu ? geometry.size.width/2 : 0)
.disabled(self.showMenu ? true : false)
그러나 지금까지는 메뉴가 애니메이션 없이 계속 표시됩니다. 대신 "슬라이드 인" 전환을 사용하려고 합니다.
따라서 MainView 의 버튼 동작을 withAnimation 문으로 래핑합니다.
Button(action: {
withAnimation {
self.showMenu = true
}
}) {
Text("Show Menu")
}
이제 MenuView에 전환 수정자를 첨부 하고 메뉴가 왼쪽에서 이동하도록 지정할 수 있습니다.
MenuView()
.frame(width: geometry.size.width/2)
.transition(.move(edge: .leading))
힌트 : 라이브 미리보기에서 애니메이션이 실행되고 있지 않다면 일반 시뮬레이터에서 앱을 실행하세요.
메뉴를 닫으려면 스와이프하세요
오른쪽에서 왼쪽으로 스와이프하여 메뉴를 다시 닫을 수 있기를 원합니다. 이를 위해 소위 드래그 제스처를 사용합니다. ContentView의 본문 내에서 선언 하고 나머지 보기의 콘텐츠를 return 키워드로 표시하여 이러한 제스처를 만듭니다 .
var body: some View {
let drag = DragGesture()
return GeometryReader { geometry in
//...
}
}
충분히 멀리 스와이프하면 showMenu State를 다시 false 로 설정하여 메뉴를 닫고 싶습니다 . 이를 위해 드래그 제스처에 .onEnded 수정자를 사용합니다 .
let drag = DragGesture()
.onEnded {
}
여기에서 사용자가 스와이프 제스처로 특정 임계값을 초과했는지 확인합니다. 이 경우 메뉴를 닫습니다.
let drag = DragGesture()
.onEnded {
if $0.translation.width < -100 {
withAnimation {
self.showMenu = false
}
}
}
이제 생성된 제스처를 ContentView 에 간단히 첨부할 수 있습니다 .
ZStack(alignment: .leading) {
//...
}
.gesture(drag)
버거 버튼 구현 🍔
마지막으로, 우리는 또한 소위 햄버거 아이콘을 사용하여 메뉴를 열고 닫을 수 있는 가능성을 갖고 싶습니다. 이를 위해 ContentView 의 GeometryReader를 NavigationView로 래핑하고 탐색 모음 제목을 추가합니다.
return NavigationView {
GeometryReader { geometry in
//...
}
.navigationBarTitle("Side Menu", displayMode: .inline)
}
이제 선행 인수와 함께 .navigationBarItems 수정자를 사용하여 탐색 모음의 왼쪽에 항목을 추가할 수 있습니다 .
.navigationBarTitle("Side Menu", displayMode: .inline)
.navigationBarItems(leading: (
))
이제 적절한 시스템 아이콘을 추가하고 showMenu 상태를 토글하는 버튼으로 래핑합니다
.navigationBarItems(leading: (
Button(action: {
withAnimation {
self.showMenu.toggle()
}
}) {
Image(systemName: "line.horizontal.3")
.imageScale(.large)
}
))
이제 앱을 실행하면 MainView의 버튼과 스와이프 제스처와 탐색 모음의 "햄버거" 아이콘을 사용하여 사이드 메뉴를 열고 닫을 수 있습니다 .
결론
https://blckbirds.com/post/side-menu-hamburger-menu-in-swiftui/
위 강의를 따라해 보았다.
Author And Source
이 문제에 관하여([SwiftUI] 사이드 메뉴 만들기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@jhchoo/SwiftUI-사이드-메뉴-만들기저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)