Building Tabbed Views in SwiftUI

The SwiftUI TabView component allows the user to navigate between different child views by selecting tab items located in a tab bar. This chapter will work through an example project intended to demonstrate how to implement a TabView based interface in a SwiftUI app.

1.1 An Overview of SwiftUI TabView

Tabbed views are created in SwiftUI using the TabView container view and consist of a range of child views which represent the screens through which the user will navigate.

The TabView presents a tab bar at the bottom of the layout which contains the tab items used to navigate between the child views. A tab item is applied to each content view using a modifier and can be customized to contain Text and Image views (other view types are not supported in tab items).

The currently selected tab may also be controlled programmatically by adding tags to the tab items.

Figure 27‑1 shows an example TabView layout:

Figure 27‑1

1.2 Creating the TabViewDemo App

Launch Xcode and select the option to create a new Single View App named TabViewDemo with the User Interface option set to SwiftUI.

1.3 Adding the TabView Container

With the ContentView.swift file loaded into the code editor, delete the default “Hello World” Text view and add a TabView as follows:

import SwiftUI

struct ContentView: View {

    var body: some View {
        TabView {
          
        }
    }
}

1.4 Adding the Content Views

Next, add three content views to the layout. For the purposes of this example Text views will be used, but in practice these are likely to be more complex views consisting of stack layouts (note the addition of a font modifier to increase the size of the content text):

var body: some View {

    TabView {
        Text("First Content View")
        Text("Second Content View")
        Text("Third Content View")
    }
    .font(.largeTitle)
}

1.5 Adding the Tab Items

When the layout is now previewed, the first content view will be visible along with the tab bar located along the bottom edge of the screen. Since no tab items have been added, the tab bar is currently empty. Clearly the next step is to apply a tab item to each content view using the tabItem() modifier. In this example, each tab item will contain a Text and an Image view:

var body: some View {
    TabView {
        Text("First Content View")
            .tabItem {
                Image(systemName: "1.circle")
                Text("Screen One")
            }
        Text("Second Content View")
            .tabItem {
                Image(systemName: "2.circle")
                Text("Screen Two")
            }
        Text("Third Content View")
            .tabItem {
                Image(systemName: "3.circle")
                Text("Screen Three")
            }
    }
    .font(.largeTitle)
}

With the changes made, verify that the tab items now appear in the tab bar before using Live Preview to test that clicking on a tab item displays the corresponding content view. The completed app should resemble that illustrated in Figure 27‑1 above.

1.6 Adding Tab Item Tags

To control the currently selected tab in code, a tag needs to be added to each tab item and a state property declared to store the current selection as follows:

struct ContentView: View {

    @State private var selection = 1

    var body: some View {

        TabView() {
            Text("First Content View")
                .tabItem {
                    Image(systemName: "1.circle")
                    Text("Screen One")
                }.tag(1)

            Text("Second Content View")
                .tabItem {
                    Image(systemName: "2.circle")
                    Text("Screen Two")
                }.tag(2)

            Text("Third Content View")
                .tabItem {
                    Image(systemName: "3.circle")
                    Text("Screen Three")
                }.tag(3)
        }
        .font(.largeTitle)
    }
}

Next, bind the current selection value of the TabView to the selection state property:

var body: some View {
    TabView(selection: $selection) {
        Text("First Content View")
            .tabItem {
.
.

Any changes to the selection state property to a different value within the tag range (in this case a value between 1 and 3) elsewhere in the view will now cause the tabbed view to switch to the corresponding content view.

Test this behavior by changing the value assigned to the selection state property while the app is running in live preview mode.

1.7 Summary

The SwiftUI TabView container provides a mechanism via which the user can navigate between content views by selecting tabs in a tab bar. The TabView is implemented by declaring child content views and assigning a tab item to each view. The tab items appear in the tab bar and can be constructed from a Text view, an Image view or a combination of Text and Image views.

To control the current selection of a TabView programmatically, each tab item must be assigned a tag containing a unique value, binding the TabView current selection value to a state property.