Demonstrating the use of a Sidebar, SplitView and Navigation styles in a multiplatform app.

Last update: Apr 1, 2022

Navigation Styles for Multiplatform Apps

Demonstrate the use of a Sidebar, SplitView, TabView and Navigation styles in a multiplatform app.

NavigationView with List

The basic form of navigation using a NavigationView, List and NavigationLink is as follows:

import SwiftUI

struct ContentView: View {
    
    var colors: [Color] = [.red, .green, .blue, .yellow, .purple]
    
    var body: some View {
        NavigationView {
            List {
                ForEach(1...5, id: \.self) { val in
                    NavigationLink(destination: ViewLevel2(linkText: String(val), color: colors[val-1])) {
                        Text("Link\(val)")
                            .font(.largeTitle)
                            .foregroundColor(colors[val-1])
                            .padding()
                    }
                }
            }
        }
    }
}

struct ViewLevel2: View {
    
    var linkText = "Test"
    var color: Color = .black
    
    var body: some View {
        VStack {
            Text("ViewLevel2")
                .font(.largeTitle)
                .padding()
            
            Text("Text: \(linkText)")
                .font(.title)
                .foregroundColor(color)
        }
    }
}

The default behavior of NavigationView can be controlled using the .navigationViewStyle() modifier. You can specify either of:

  • StackNavigationViewStyle(), which displays only one view at a time
  • DoubleColumnNavigationViewStyle() which displays two views in "split view" arrangement

Note that SwiftUI does not have a direct equivalent of UIKit's UISplitViewController. However, NavigationView allows you to achieve much the same thing.

NavigationView {
}
.navigationViewStyle(StackNavigationViewStyle())  // "Single View"


NavigationView {
}
.navigationViewStyle(DoubleColumnNavigationViewStyle())  // "Split View"

The appearance of the app for the various devices and orientations looks like this:

iOS Portrait (iPhone 12 Pro Max)

Default (StackNavigationViewStyle) DoubleColumnNavigationViewStyle StackNavigationViewStyle
Same as default style Same as default style

iOS Landscape (iPhone 12 Pro Max)

Default (DoubleColumnNavigationViewStyle) DoubleColumnNavigationViewStyle StackNavigationViewStyle
Same as default style

iPadOS Portrait (iPad Pro 12.9")

Default (DoubleColumnNavigationViewStyle) DoubleColumnNavigationViewStyle StackNavigationViewStyle
Same as default style

iPadOS Landscape (iPad Pro 12.9")

Default (DoubleColumnNavigationViewStyle) DoubleColumnNavigationViewStyle StackNavigationViewStyle
Same as default style
Note button to hide navigation

macOS, tvOS, watchOS

macOS tvOS watchOS

Sidebar

Sidebars are an important part of UI design for larger devices (available for iOS, iPadOS and macOS). See https://developer.apple.com/design/human-interface-guidelines/ios/bars/sidebars/.

A sidebar can very easily be added by using the .listStyle(SidebarListStyle()) modifier on a List:

struct SidebarView: View {
    var body: some View {
        List {
            Label("What's New", systemImage: "wand.and.stars")
            Label("Messages", systemImage: "message")
            Label("List", systemImage: "list.bullet.rectangle")
            Section(header: Text("Personal")) {
                Label("Settings", systemImage: "gearshape")
                Label("Account", systemImage: "person.crop.circle")
                Section(header: Text("Very Personal SubMenu")) {
                    Label("Secret Stuff", systemImage: "text.badge.plus")
                    Label("Very Secret Stuff", systemImage: "lasso.sparkles")
                }
            }
        }
        .listStyle(SidebarListStyle())
        .navigationTitle("My Sidebar")
    }
}

You can add section headers to a sidebar so that disclosure indicators allow the user to collapse and expand sections.

We can make a few minimal changes to our app to get it to work with a sidebar. First, make SidebarView the startup view:

@main
struct SwiftUI_SplitViewNavDemoApp: App {
    var body: some Scene {
        WindowGroup {
//            ContentView()
            SidebarView()
        }
    }
}

Now we'll modify SidebarView to define a NavigationView for the app. Notice also how we use a NavigationView to move to ListView:

struct SidebarView: View {
    var body: some View {
        NavigationView {
            List {
                NavigationLink(destination: Text("What's New")) {
                    Label("What's New", systemImage: "wand.and.stars")
                }
                
                NavigationLink(destination: Text("Messages")) {
                    Label("Messages", systemImage: "message")
                }
                
                NavigationLink(destination: ListView()) {
                    Label("List", systemImage: "list.bullet.rectangle")
                }

                Section(header: Text("Personal")) {
                    Label("Settings", systemImage: "gearshape")
                    Label("Account", systemImage: "person.crop.circle")
                    Section(header: Text("Very Personal SubMenu")) {
                        Label("Secret Stuff", systemImage: "text.badge.plus")
                        Label("Very Secret Stuff", systemImage: "lasso.sparkles")
                    }
                }
            }
            .listStyle(SidebarListStyle())
            .navigationTitle("My Sidebar")
        }
    }
}

struct ListView: View {
    
    var colors: [Color] = [.red, .green, .blue, .yellow, .purple]
    
    var body: some View {
        List {
            ForEach(1...5, id: \.self) { val in
                NavigationLink(destination: ViewLevel2(linkText: String(val), color: colors[val-1])) {
                    Text("Link\(val)")
                        .font(.largeTitle)
                        .foregroundColor(colors[val-1])
                        .padding()
                }
            }
        }
    }
}

All the navigation links in ListView have ViewLevel2 as their destination.

So, we logically have the following arrangement:

The appearance of our app with a sidebar looks like this:

iOS Portrait (iPhone 12 Pro Max)

iOS Landscape (iPhone 12 Pro Max)

iPadOS Portrait (iPad Pro 12.9")

iPadOS Landscape (iPad Pro 12.9")

Paged Navigation (TabView)

We can add a TabbedPageView to allow us to present a collection of pages (or tabs) to the user:

struct TabbedPageView: View {
    
    var body: some View {
        TabView {
            VStack {
                Text("Hello, world!").font(.largeTitle).padding()
                Image(systemName: "face.smiling.fill")
                    .resizable()
                    .frame(width: 150, height: 150)
                    .foregroundColor(.yellow)
            }
            .tabItem { Text("Tab1") }

            Text("Hello, world2!")
            .tabItem { Text("Tab2") }

            Text("Hello, world3!")
            .tabItem { Text("Tab3") }

            Text("Hello, world4!")
            .tabItem { Text("Tab4") }
        }
        .tabViewStyle(DefaultTabViewStyle())  // PageTabViewStyle() or DefaultTabViewStyle() to show tabs
        .indexViewStyle(PageIndexViewStyle(backgroundDisplayMode: .always))
    }
}

Pages:

Tabs:

Integrate this with our sidebar app as follows:

struct SidebarView: View {
    var body: some View {
        NavigationView {
            List {
                :
                NavigationLink(destination: TabbedPageView()) {
                    Label("Messages", systemImage: "message")
                }
                :

Running the app produces:

iOS Portrait (iPhone 12 Pro Max)

iOS Landscape (iPhone 12 Pro Max)

macOS

Note that TabView on macOS doesn't support either .tabViewStyle(DefaultTabViewStyle()) or .indexViewStyle(PageIndexViewStyle(backgroundDisplayMode: .always)) so that only tabs are displayed:

GitHub

https://github.com/russell-archer/SwiftUI-SplitViewNavDemo
You might also like...

A clone of the Twitter app that allows users to log in and read, create, and interact with tweets

A clone of the Twitter app that allows users to log in and read, create, and interact with tweets

A clone of the Twitter app that allows users to log in and read, create, and interact with tweets

Mar 12, 2022

The App Brewery Complete App Development course project

 The App Brewery Complete App Development course project

Destini The App Brewery Complete App Development course project. "A Choose Your

Jan 29, 2022

Scrumdinger-ios - Built as a part of iOS app dev tutorials from app-dev-training

Scrumdinger-ios - Built as a part of iOS app dev tutorials from app-dev-training

Scrumdinger This repository contains the code written during my course of taking

Jan 23, 2022

A simple app that I created to migrate my photos from Lightroom Classic to Apple's Photos.app.

A simple app that I created to migrate my photos from Lightroom Classic to Apple's Photos.app.

CustomPhotoImporter A simple app that I created to migrate my photos from Lightroom Classic to Apple's Photos.app. This is optimised for my specific n

Apr 27, 2022

Concept for organizing View and Data layers within SwiftUI App

Concept for organizing View and Data layers within SwiftUI App

SwiftUI MVVM Concept It is not about how to create Lists and Charts and View design. It's about possibility how to organize View and Data layers withi

May 16, 2022

A simple iOS app with one default and four custom transitions.

A simple iOS app with one default and four custom transitions.

A simple iOS app with one default and four custom transitions. The app uses the same two view controllers for every transition.

Aug 18, 2021

A simple app that downloads a list of albums from iTunes and displays it in a table

A simple, sample app that downloads a list of albums from iTunes and displays it in a table. It also allows the user to bookmark albums which are then

Oct 30, 2021

An app that simplifies attendance entry, and uploads recorded attendance to a centralized Google Sheet.

An app that simplifies attendance entry, and uploads recorded attendance to a centralized Google Sheet.

NHSAttendance NHSAttendance is an app that simplifies attendance entry, and uploads recorded attendance to a centralized Google Sheet. This allows for

Apr 14, 2022

This is a basic twitter app to view, compose, favorite, and retweet tweets.

This is a basic twitter app to view, compose, favorite, and retweet tweets.

Twitter - Part II This is a basic twitter app to view, compose, favorite, and retweet tweets. Time spent: 6 hours spent in total User Stories The foll

Oct 31, 2021
Related tags
Advanced Catalyst Example with sidebar, list view, SwiftUI detail view, toolbar & AppKit bundle
Advanced Catalyst Example with sidebar, list view, SwiftUI detail view, toolbar & AppKit bundle

Advanced Catalyst Example This is an example of a Catalyst app using a three-column layout, with a primary toolbar. It includes topics such as: Drag &

Jun 24, 2022
SwiftUI project demonstrating how weak self works

SwiftUI-weak-self SwiftUI project demonstrating how weak self works Inspired by Swiftful

Nov 9, 2021
Exchanger - a simple iOS application demonstrating one of approaches to implement VIPER 💎 architecture in modern Objective-C
Exchanger - a simple iOS application demonstrating one of approaches to implement VIPER 💎 architecture in modern Objective-C

The Exchanger is a simple iOS application demonstrating one of approaches to implement VIPER ?? architecture in modern Objective-C.

Feb 12, 2022
SwiftUI Navigation example app

SwiftUINavigationExample SwiftUI Navigation example app. Navigation is managed by a single class called NavSwitches. This contains all the booleans th

Feb 18, 2022
AnimeSearch - A simple app that shows how to use Anilist GraphQL based API with Apollo
AnimeSearch - A simple app that shows how to use Anilist GraphQL based API with Apollo

AnimeSearch A simple app that shows how to use Anilist GraphQL based API with Ap

Apr 26, 2022
This sample app use the Star Wars public api to show a list of characters

StarWars-MVVM In this sample app, I use the Star Wars public api to show a list of characters from the Star Wars movie series. There are two goals I w

Mar 8, 2022
Tipsy - Bill splitting and tip calculating App developed during iOS & Swift classes - The Complete App Development Bootcamp
Tipsy - Bill splitting and tip calculating App developed during iOS & Swift classes - The Complete App Development Bootcamp

Tipsy ?? Bill splitting and tip calculating App developed during iOS & Swift cla

Jan 27, 2022
MemeMe, students will create an app that enables a user to take a picture, and add text at the top and bottom to form a meme
MemeMe, students will create an app that enables a user to take a picture, and add text at the top and bottom to form a meme

With this first version of MemeMe, students will create an app that enables a user to take a picture, and add text at the top and bottom to form a meme. The user will be able to share the photo on Facebook and Twitter and also by SMS or email.

Dec 11, 2021