Mastering NavigationView in SwiftUI: A Comprehensive Guide
Written on
Chapter 1: Introduction to NavigationView
In SwiftUI, the NavigationView component facilitates a structured method for transitioning between views, including the ability to return to previously viewed screens. This feature is essential for applications with multiple screens that showcase various functionalities. This tutorial is part of my ongoing series on SwiftUI.
To begin, either create a new project or open an existing one for practice. The following guide provides a detailed walkthrough on setting up a new project.
How Does NavigationView Work?
The syntax for implementing a NavigationView is as follows:
NavigationView {
NavigationLink(destination: //Next view) {
//Label for user interaction}
//Link appearance
}
Let's illustrate this with a straightforward example by filling in the comments in the syntax:
struct ContentView: View {
var body: some View {
NavigationView {
NavigationLink(destination: Text("This is the second view")) {
Text("Go to second view")}
}
} //body
} //ContentView
Once you run the code and select "Go to the second view," you will transition to a new screen displaying "This is the second view."
In a practical application, it's advisable to create a separate struct for the second view. By holding the Command key and clicking on Text, a list of options will pop up. Choose "Extract Subview."
This will generate a subview in the form of a struct named ExtractedView. To adhere to best practices, rename it to SecondView.
Adding a Navigation Title
To enhance your app, let's set a title using the navigationTitle modifier:
NavigationView {
NavigationLink(destination: SecondView()) {
Text("Go to second view")}
.navigationTitle("SwiftUI Navigation")
}
By default, the navigation bar will display a large title that shrinks as you scroll up. To maintain a compact navigation bar, use the .inline modifier like this:
NavigationLink(destination: SecondView()) {
Text("Go to second view")
}
.navigationTitle("SwiftUI Navigation")
.navigationBarTitleDisplayMode(.inline)
Customizing Navigation Bar Appearance
As of now, SwiftUI lacks direct modifiers for adjusting the navigation bar's font and color. Instead, you can utilize UINavigationBarAppearance from UIKit. For instance, to change the title color to blue and adjust the font style to Savoye LET, you can add the following code in ContentView:
init() {
let navBarAppearance = UINavigationBarAppearance()
navBarAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.blue, .font: UIFont(name: "Savoye LET", size: 40)!]
navBarAppearance.titleTextAttributes = [.foregroundColor: UIColor.blue, .font: UIFont(name: "Savoye LET", size: 20)!]
UINavigationBar.appearance().standardAppearance = navBarAppearance
UINavigationBar.appearance().scrollEdgeAppearance = navBarAppearance
UINavigationBar.appearance().compactAppearance = navBarAppearance
} //init
In this code, we established a UINavigationBarAppearance constant named navBarAppearance, allowing us to configure attributes like largeTitleTextAttributes and titleTextAttributes. These configurations are then applied to standardAppearance, scrollEdgeAppearance, and compactAppearance.
The navigation bar will now appear as shown below based on the above settings:
Changing the Back Button Color
The default color of the navigation view's back button is blue. You can alter this color using UINavigationBarAppearance. To change the back button's color to red, add the following line within init():
UINavigationBar.appearance().tintColor = .red
Utilizing NavigationView with a ForEach List
Now, let's implement NavigationView within a ForEach List, a crucial concept for many content-driven applications. If you're new to List and ForEach, it’s advisable to review a foundational tutorial before advancing.
We will create an application that navigates to the respective view upon tapping.
Before you begin, gather the images you wish to use. If you don't have any, you can download photos from Unsplash. Ensure all images are imported into the Assets directory. If you're unfamiliar with image handling in SwiftUI, consult this tutorial.
Once your assets are ready, create a new struct to hold the images and text:
struct Collections: Identifiable {
var id = UUID()
var name: String
var image: String
var content: String
}
Next, set up an array to store your data:
var collections = [
Collections(name: "Cafe", image: "rr-abrot", content: "Cafe. Lorem ipsum dolor sit amet."),
Collections(name: "Home", image: "ian-harber", content: "Home. Lorem ipsum dolor sit amet."),
Collections(name: "Commute", image: "charles-forerunner", content: "Commute. Lorem ipsum dolor sit amet."),
Collections(name: "Travel", image: "andrew-neel", content: "Travel. Lorem ipsum dolor sit amet."),
Collections(name: "Public", image: "clay-banks", content: "Public. Lorem ipsum dolor sit amet."),
Collections(name: "Office", image: "kate-sade", content: "Office. Lorem ipsum dolor sit amet."),
Collections(name: "Conference", image: "nastuh-abootalebi", content: "Conference. Lorem ipsum dolor sit amet.")
]
Make sure to update the image names in the array to match the files you will be using.
Next, design the appearance of the rows by creating a separate struct:
struct ImageLabelRow: View {
var collection: Collections
var body: some View {
ZStack(alignment: .trailing) {
Image(collection.image)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(height: 150)
.cornerRadius(20)
.overlay(
Rectangle()
.foregroundColor(.black)
.cornerRadius(20)
.opacity(0.4)
)
Text(collection.name)
.font(.system(.largeTitle, design: .rounded))
.fontWeight(.black)
.foregroundColor(.white)
.padding()
}
}
}
When a link is tapped, it should navigate to another view. Let's create a simple version of this with the following code:
struct DetailView: View {
var collection: Collections
var body: some View {
Text(collection.content)
.font(.body)}
}
Now that all external structs are prepared, let's implement the NavigationView within the ContentView's body:
NavigationView {
List(collections) { index in
ZStack {
ImageLabelRow(collection: index)
NavigationLink(destination: DetailView(collection: index)) {}
} //ZStack
} //List
.navigationTitle("Where are you?")
} //NavigationView
In this code, we created a NavigationView that contains a ForEach List to display all items from the collections variable. The ImageLabelRow struct is utilized for the list's design, paired with its corresponding Navigation Link leading to the DetailView.
Run the application and test the links; they should redirect you to their respective contents.
For the complete source code, check out the GitHub repository.
In the next tutorial, we will explore the fundamentals of animation.
May your coding journey be successful,
- Arc
The first video titled "The Complete Guide to NavigationView in SwiftUI" provides an in-depth look at using NavigationView effectively within your applications.
The second video, "SwiftUI Navigation - NavigationView & NavigationLink Tutorial," offers a comprehensive tutorial on implementing NavigationView and NavigationLink in SwiftUI.