In this tutorial we’re going to learn how use NavigationView’s navigationBarItems button to present a new sheet view modally.
In order to accomplish this, we’re going to follow these steps:
- Create a NavigationView
- Add a button to the NavigationView
- Create a new sheet view which we wish to present
- Add action to the button to present the new sheet view
- For bonus points: dismiss the new sheet view with a Done button
Create a NavigationView
Add a NavigationView with some content (in this case, a simple text view) and give it a title using the navigationBarTitle() modifier:
struct ContentView: View {
var body: some View {
NavigationView {
Text("Content")
.navigationBarTitle("SwiftUI Tutorials")
}
}
}
Add a button to the NavigationView
Add a trailing button to to the NavigationView using navigationBarItems() modifier. We’re using an SF Symbol in place of the button. Update the NavigationView like this:
NavigationView {
Text("Content")
.navigationBarTitle("SwiftUI Tutorials")
.navigationBarItems(trailing:
Button(action: {
print("Navigation bar item action")
}) {
Image(systemName: "bell.circle.fill")
.font(Font.system(.title))
}
)
}
At this point, the result should look like this:
Create new sheet view
Now, let’s add a brand new view to our project which is going to be presented when user taps the bell button. We’re going to call it a SheetView and it’s also going to be a NavigationView with a title. In this case, the title of the navigation bar is styled to be displayed inline (in the middle of the navigation bar):
struct SheetView: View {
var body: some View {
NavigationView {
Text("List of notifications")
.navigationBarTitle(Text("Notifications"), displayMode: .inline)
}
}
}
This view doesn’t do much right now but we’re going to use it in the next section.
Present a new sheet view as a modal
In order to present the newly created SheetView when user taps the bell button, two things need to happen in the ContentView:
- Add new boolean @State variable called showSheetView to the ContentView which will control whether to show SheetView
- Use sheet(isPresented:) modifier which presents a sheet based on the isPresented binding (which will point at our showSheetView state variable)
Take a look at updated code:
struct ContentView: View {
@State var showSheetView = false
var body: some View {
NavigationView {
Text("Content")
.navigationBarTitle("SwiftUI Tutorials")
.navigationBarItems(trailing:
Button(action: {
self.showSheetView.toggle()
}) {
Image(systemName: "bell.circle.fill")
.font(Font.system(.title))
}
)
}.sheet(isPresented: $showSheetView) {
SheetView()
}
}
}
Tapping the bell button presents the SheetView!
In order to dismiss the SheetView, user needs to pull down on it (swipe down). However, what if we wanted to add a “Done” button to the SheetView which will dismiss it when tapped? Let’s explore how to achieve it.
Dismiss the sheet view with a Done button
The new sheet view with a Done button will look like this:
First of all, we need to add a trailing Done button to the navigation bar of the SheetView. We’re going to do it by using the navigationBarItems(trailing:) modifier just like we did for the ContentView earlier.
Then, we need to declare a @Binding variable within the SheetView which will actually reference the showSheetView variable from ContentView (because it controls whether the SheetView is presented or not).
Finally, we need to pass the showSheetView’s binding reference to the SheetView.
The final code for SheetView should look like this:
struct SheetView: View {
@Binding var showSheetView: Bool
var body: some View {
NavigationView {
Text("List of notifications")
.navigationBarTitle(Text("Notifications"), displayMode: .inline)
.navigationBarItems(trailing: Button(action: {
print("Dismissing sheet view...")
self.showSheetView = false
}) {
Text("Done").bold()
})
}
}
}
And the ContentView should look like this:
struct ContentView: View {
@State var showSheetView = false
var body: some View {
NavigationView {
Text("Content")
.navigationBarTitle("SwiftUI Tutorials")
.navigationBarItems(trailing:
Button(action: {
self.showSheetView.toggle()
}) {
Image(systemName: "bell.circle.fill")
.font(Font.system(.title))
}
)
}.sheet(isPresented: $showSheetView) {
SheetView(showSheetView: self.$showSheetView)
}
}
}
Take a look at final result of this tutorial:
Related tutorials:
- How to add button to navigation bar in SwiftUI
- How to present a sheet modally in SwiftUI
- How to add NavigationView to List in SwiftUI and show detail view using NavigationLink
Take a look at Apple’s official NavigationView and navigationBarItems(trailing:) documentations.