Context Menu in SwiftUI

DevTechie Inc
May 11, 2023

Context menu is a view which allows us to present a situationally specific menu that enables taking actions relevant to the task in hand. On iOS, context menu is displayed when the view is pressed and hold for a short while.

Example of context menu.

We can use contextMenu modifier to add context menu to a view in our app’s user interface.

Let’s put an example to create a simple context menu.

VStack {
    Text("DevTechie")
        .font(.title)
        .padding()
        .foregroundStyle(.white)
        .background(.orange, in: RoundedRectangle(cornerRadius: 20))
        .contextMenu {
            Button("Learn SwiftUI") {  }
            Button("Learn UIKit") {  }
            Button("Show more") {  }
        }
}

We can compose menu by returning controls like Button, Toggle or Picker view from menuItems closure.

Let’s update our view to have Toggle buttons as context menu items.

struct ContentView: View {
    @State private var receiveEmail = false
    @State private var showSettings = true
    
    var body: some View {
        VStack {
            Text("DevTechie")
                .font(.title)
                .padding()
                .foregroundStyle(.white)
                .background(.orange, in: RoundedRectangle(cornerRadius: 20))
                .contextMenu {
                    Toggle("Receive email?", isOn: $receiveEmail)
                    Toggle("Show Settings?", isOn: $showSettings)
                }
            
            HStack {
                Text("Current preferences: ")
                Group {
                    if receiveEmail {
                        Image(systemName: "envelope.circle.fill")
                    }
                    if showSettings {
                        Image(systemName: "gear.circle")
                    }
                }
                .font(.largeTitle)
                
            }
        }
    }
}

Context menu supports sections as well so we can have menu items within sections to group related items. Let’s update our example to create two sections.

struct ContentView: View {
    @State private var receiveEmail = false
    @State private var showSettings = true
    
    var body: some View {
        VStack {
            Text("DevTechie")
                .font(.title)
                .padding()
                .foregroundStyle(.white)
                .background(.orange, in: RoundedRectangle(cornerRadius: 20))
                .contextMenu {
                    Section(header: Text("About DevTechie")) {
                        Button("Learn SwiftUI") {}
                        Button("Learn UIKit") {}
                    }
                    Section(header: Text("Preferences")) {
                        Toggle("Receive email?", isOn: $receiveEmail)
                        Toggle("Show Settings?", isOn: $showSettings)
                    }
                }
            
            HStack {
                Text("Current preferences: ")
                Group {
                    if receiveEmail {
                        Image(systemName: "envelope.circle.fill")
                    }
                    if showSettings {
                        Image(systemName: "gear.circle")
                    }
                }
                .font(.largeTitle)
                
            }
        }
    }
}