{"id":2718,"date":"2025-11-11T17:02:20","date_gmt":"2025-11-11T08:02:20","guid":{"rendered":"https:\/\/www.freelifemakers.org\/wordpress\/?p=2718"},"modified":"2025-11-22T10:00:30","modified_gmt":"2025-11-22T01:00:30","slug":"swiftdrawer-menu","status":"publish","type":"post","link":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/2025\/11\/11\/swiftdrawer-menu\/","title":{"rendered":"[Swift]Drawer Menu"},"content":{"rendered":"\n<p>\ud83d\udc49\ud83c\udffb Drawer Menu\ub97c swift\uc5d0\uc11c \uad6c\ud604\ud558\ub294 \ubc29\ubc95\uc785\ub2c8\ub2e4<br>How to implement a Drawer Menu in Swift<\/p>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb Drawer Menu\uc758 \ud575\uc2ec\uc740 \uc560\ub2c8\uba54\uc774\uc158 \uc18d\uc131\uc744 \uc0ac\uc6a9\ud574\uc11c \uba54\ub274 \uc704\uce58\ub97c \uc774\ub3d9\ud558\ub294 \uac83\uc785\ub2c8\ub2e4.<br>The key to the Drawer Menu is using animation properties to move the menu position.<\/p>\n\n\n\n<p>\u2714\ufe0fContentView.swift<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import SwiftUI\n\nstruct ContentView: View {\n    @State private var showMenu = false\n    @State private var selectedMenu = \"Home\"\n    @State private var hideStatusBar = false\n\n    var body: some View {\n        ZStack {\n            \/\/ Main content\n            NavigationView {\n                VStack {\n                    switch selectedMenu {\n                    case \"Home\":\n                        HomeScreen()\n                       \/\/ HomeScreen2()\n                    case \"Search\":\n                        SearchScreen()\n                       \/\/ SearchScreen2()\n                    case \"Settings\":\n                        SettingsScreen()\n                       \/\/ SettingsScreen2()\n                    default:\n                        HomeScreen()\n                    }\n                }\n                .navigationBarTitle(Text(selectedMenu), displayMode: .inline)\n                .navigationBarItems(leading: Button(action: {\n                    withAnimation(.easeInOut(duration: 0.3)) {\n                        showMenu.toggle()\n                    }\n                }) {\n                    Image(systemName: \"line.3.horizontal\")\n                        .imageScale(.large)\n                })\n            }\n            .disabled(showMenu)\n            \n            \/\/ \ubc18\ud22c\uba85 \ubc30\uacbd (\ud56d\uc0c1 \uc874\uc7ac + opacity\ub85c \uc81c\uc5b4)\n            \/\/ Semi-transparent background (always present + controlled by opacity)\n            Color.black\n                .opacity(showMenu ? 0.4 : 0.0)\n                .animation(.easeInOut(duration: 0.3), value: showMenu)\n                .edgesIgnoringSafeArea(.all)\n                .ignoresSafeArea() \/\/  Status Bar \ud3ec\ud568\n                .edgesIgnoringSafeArea(.all) \/\/ Status Bar \ud3ec\ud568(ios15\uc774\uc804 \uc6a9)\n                .onTapGesture {\n                    if showMenu {\n                        withAnimation(.easeInOut(duration: 0.3)) {\n                            showMenu = false\n                        }\n                    }\n                }\n            \n            \/\/ Drawer (offset\uc73c\ub85c \uc2ac\ub77c\uc774\ub4dc \uc778\/\uc544\uc6c3)\n            \/\/ Drawer (slides in\/out with offset)\n            \n            \/\/ Drawer\ub294 Dynamick Island\ub294 \uac00\ub9b4 \uc218 \uc5c6\uc74c(\uc2dc\uacc4 \uc6b0\uce21 \ud0c0\uc6d0)\n            \/\/ Drawer cannot cover Dynamick Island (oval on the right side of the clock)\n            HStack {\n                \n                \/\/ \ud654\uba74\uc758\uc815\ubcf4 \uacc4\uc0b0\ud560\ub54c GeometryReader\uc0ac\uc6a9\n                \/\/ Use GeometryReader when calculating screen information\n                GeometryReader { geo in\n                    VStack(alignment: .leading) {\n                        Text(\"Menu Title\")\n                            .font(.title)\n                            .padding(.top, 50)\n                            .padding(.bottom, 20)\n                        \n                        \/\/ \uac01 \uba54\ub274 \/ Each Menu\n                        DrawerMenuItem(title: \"Home\", selectedMenu: $selectedMenu, showMenu: $showMenu)\n                        DrawerMenuItem(title: \"Search\", selectedMenu: $selectedMenu, showMenu: $showMenu)\n                        DrawerMenuItem(title: \"Settings\", selectedMenu: $selectedMenu, showMenu: $showMenu)\n                        Spacer() \/\/ \ub098\uba38\uc9c0 \uacf5\uac04 \ucc28\uc9c0 \/ Takes up the rest of the space\n\n                    } \/\/ VStack\n                    \/\/.frame(width: 250, height: UIScreen.main.bounds.height) \/\/ \ud654\uba74\uc804\uccb4 \ub192\uc774\ub85c \uc124\uc815 \/ Set to full screen height(deprecated)\n                    .frame(width:250, height:geo.size.height) \/\/ \ub4dc\ub85c\uc5b4\ub97c \uc804\uccb4 \ub192\uc774\ub85c\uc124\uc815,geometry reader\uc0ac\uc6a9 \/ Set the drawer to full height, using the geometry reader\n                    .padding(.horizontal, 16)\n                    .background(Color(UIColor.systemBackground))\n                }\n\n                \n                Spacer()\n            } \/\/ HStack(Drawer)\n            .offset(x: showMenu ? 0 : -260) \/\/ \uc2a4\ud0dd\uc704\uce58 0\uc740 \ud654\uba74 \uc548 -260\ud654\uba74 \ubc16 \/ Stack position 0 is inside the screen -260 is outside the screen\n            .animation(.easeInOut(duration: 0.3), value: showMenu) \/\/ \uc5d0\ub2c8\uba54\uc774\uc158\uc801\uc6a9 \/ Apply animation\n            \n            \/*\n                 animation\uc744 \uc9c0\uc815\ud558\uc9c0\uc54a\uace0 offset\ub9cc \uc9c0\uc815\ud574\ub3c4 ios\uc5d0\uc11c\ub294 \uc554\ubb35\uc801\uc73c\ub85c \uc560\ub2c8\uba54\uc774\uc158 \ucc98\ub9ac\ud568\n                 animation\uc744 \uc788\uc73c\uba74 \ub354 \uc790\uc138\ud55c \uc124\uc815\uc774 \uac00\ub2a5\ud568.\n                 Even if you only specify an offset without specifying animation, iOS implicitly handles animation.\n                 Animation allows for more detailed settings.\n             *\/\n            \n            \n        }\n        .statusBar(hidden: hideStatusBar) \/\/ Drawer\uc5f4\ub9b4 \uacbd\uc6b0 Statusbar\uc228\uae40 \/ Hide Statusbar when Drawer is opened\n        .onChange(of: showMenu) { oldValue, newValue in\n            hideStatusBar = newValue\n        }\n\n            \n        \/\/zstack\n    } \/\/ body\n} \/\/ContentView\n\n\/\/ MARK: - DrawerMenuItem\nstruct DrawerMenuItem: View {\n    let title: String \/\/Home,Search,Settings\n    @Binding var selectedMenu: String \/\/ Default value \"Home\"\n    @Binding var showMenu: Bool \/\/ true,false\n    \/**\n           @Binding :  \ubd80\ubaa8\ubdf0\uc758 \uc0c1\ud0dc(@State)\ub97c \uc790\uc2dd\ubdf0\uac00  \uc218\uc815 \ud560 \uc218 \uc788\uac8c \uc5f0\uacb0\ud574\uc8fc\ub294 \ucc38\uc870 ,c++\uc758 \ud3ec\uc778\ud130\uc640 \uac19\uc740 \uac1c\ub150\n     *\/\n\n    var body: some View {\n        Button(action: {\n            withAnimation(.easeInOut(duration: 0.3)) {\n                \/\/ \uba54\ub274\ud0c0\uc774\ud2c0 \ubcc0\uacbd(\ud30c\ub77c\uba54\ud130\ub85c \uc785\ub825\ub41c \uac12\uc744 \ub300\uc785) \/ Change menu title (substitute the value entered as a parameter)\n                selectedMenu = title\n                showMenu = false \/\/ Close Drawer\n            }\n        }) {\n            HStack {\n                Text(title) \/\/ Home,Search,Settings\n                    .font(.headline)\n                    .foregroundColor(selectedMenu == title ? .blue : .primary)\n                Spacer()\n            }\n            .padding(.vertical, 10)\n        }\n    }\n}\n\n\/\/ MARK: - Screens(\ub85c\uceec)\nstruct HomeScreen: View {\n    var body: some View {\n    Text(\"\ub85c\uceec\ud654\uba74\/Local screen.\")\n    Text(\"\ud648 \ud654\uba74\uc785\ub2c8\ub2e4.\/Home Screen\").font(.title).padding()\n    }\n}\nstruct SearchScreen: View {\n    var body: some View {\n        Text(\"\ub85c\uceec\ud654\uba74.\/ Local Screen\")\n        Text(\"\uac80\uc0c9 \ud654\uba74\uc785\ub2c8\ub2e4. \/ Search Screen\").font(.title).padding()\n    }\n}\nstruct SettingsScreen: View {\n    var body: some View {\n        Text(\"\ub85c\uceec\ud654\uba74. \/ Local Screen\")\n        Text(\"\uc124\uc815 \ud654\uba74\uc785\ub2c8\ub2e4. \/ Settings Screen\").font(.title).padding()\n    }\n}\n\n\/\/ MARK: - Preview\n#Preview {\n    ContentView()\n}\n<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0fScreenShot<\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"481\" height=\"1024\" data-id=\"2721\" src=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2025\/11\/swift-drawer1-481x1024.png\" alt=\"\" class=\"wp-image-2721\" srcset=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2025\/11\/swift-drawer1-481x1024.png 481w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2025\/11\/swift-drawer1-141x300.png 141w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2025\/11\/swift-drawer1.png 538w\" sizes=\"auto, (max-width: 481px) 100vw, 481px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"497\" height=\"1024\" data-id=\"2722\" src=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2025\/11\/swift-drawer2-497x1024.png\" alt=\"\" class=\"wp-image-2722\" srcset=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2025\/11\/swift-drawer2-497x1024.png 497w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2025\/11\/swift-drawer2-145x300.png 145w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2025\/11\/swift-drawer2.png 546w\" sizes=\"auto, (max-width: 497px) 100vw, 497px\" \/><\/figure>\n<\/figure>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"[Kotlin compose ,Swift] DrawerMenu\" width=\"560\" height=\"315\" src=\"https:\/\/www.youtube.com\/embed\/KNNgpK_lSZ0?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>\ud83d\udc49\ud83c\udffb Drawer Menu\ub97c swift\uc5d0\uc11c \uad6c\ud604\ud558\ub294 \ubc29\ubc95\uc785\ub2c8\ub2e4How to implement a Drawer Menu in Swift \ud83d\udc49\ud83c\udffb Drawer Menu\uc758 \ud575\uc2ec\uc740 \uc560\ub2c8\uba54\uc774\uc158 \uc18d\uc131\uc744 \uc0ac\uc6a9\ud574\uc11c \uba54\ub274 \uc704\uce58\ub97c \uc774\ub3d9\ud558\ub294 \uac83\uc785\ub2c8\ub2e4.The key to the Drawer Menu is using animation properties to move the menu position. \u2714\ufe0fContentView.swift \u2714\ufe0fScreenShot<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[19,1],"tags":[],"class_list":["post-2718","post","type-post","status-publish","format-standard","hentry","category-swift","category-uncategorized","missing-thumbnail"],"_links":{"self":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/2718","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/comments?post=2718"}],"version-history":[{"count":3,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/2718\/revisions"}],"predecessor-version":[{"id":2778,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/2718\/revisions\/2778"}],"wp:attachment":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/media?parent=2718"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/categories?post=2718"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/tags?post=2718"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}