Skip to content

Instantly share code, notes, and snippets.

@florentmorin
Created June 2, 2021 09:57
Show Gist options
  • Save florentmorin/beaa0aaf7aa831546642f901a9f46784 to your computer and use it in GitHub Desktop.
Save florentmorin/beaa0aaf7aa831546642f901a9f46784 to your computer and use it in GitHub Desktop.
A SwiftUI Burger menu
//
// ContentView.swift
// SwiftUIBurgerMenu
//
// Created by Florent Morin on 02/06/2021.
//
import SwiftUI
import Foundation
extension Notification.Name {
static let displayBurgerMenu = Self.init("DisplayBurgerMenuNotification")
static let hideBurgerMenu = Self.init("HideBurgerMenuNotification")
}
struct RootNavigationView: View {
var title: String = "Navigation"
var body: some View {
NavigationView {
List {
ForEach(0...20, id: \.self) { val in
NavigationLink(
destination: Text("Detail \(val)").navigationTitle(Text("Detail"))) {
Text("Go to \(val)")
}
}
}
.navigationTitle(Text(title))
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button(action: {
NotificationCenter.default.post(name: .displayBurgerMenu, object: nil)
}) {
Image(systemName: "line.horizontal.3")
}
}
}
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
struct ContentView: View {
@State var isBurgerMenuDisplayed = false
@State var selectedMenuItem = 1
var body: some View {
ZStack {
if selectedMenuItem == 1 {
RootNavigationView(title: "Navigation 1")
.allowsHitTesting(!isBurgerMenuDisplayed)
} else {
RootNavigationView(title: "Navigation 2")
.allowsHitTesting(!isBurgerMenuDisplayed)
}
ZStack(alignment: .leading) {
Rectangle()
.foregroundColor(.black.opacity(isBurgerMenuDisplayed ? 0.5 : 0))
.animation(.easeOut(duration: 0.3))
.onTapGesture {
NotificationCenter.default.post(name: .hideBurgerMenu, object: nil)
}
List {
Section(header: VStack {
Text("Menu")
.font(.title.bold())
.frame(height: 100)
}) {
ForEach(1...2, id: \.self) { val in
Button(action: {
selectedMenuItem = val
NotificationCenter.default.post(name: .hideBurgerMenu, object: nil)
}) {
Text("Navigation \(val)")
}
}
}
}
.frame(width: 280)
.frame(maxHeight: .infinity)
.offset(x: isBurgerMenuDisplayed ? 0 : -200, y: 0)
.animation(.easeOut(duration: 0.3))
}
.allowsHitTesting(isBurgerMenuDisplayed)
.accessibilityAddTraits(.isModal)
.opacity(isBurgerMenuDisplayed ? 1 : 0)
.animation(isBurgerMenuDisplayed ? .none : .easeOut(duration: 0.3))
}
.onReceive(NotificationCenter.default.publisher(for: .hideBurgerMenu)) { _ in
isBurgerMenuDisplayed = false
}
.onReceive(NotificationCenter.default.publisher(for: .displayBurgerMenu)) { _ in
isBurgerMenuDisplayed = true
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment