Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

macOS SwiftUI App Tab View with Segmented Control in Toolbar

I am trying to create a macOS app with SwiftUI. I need a TabView or something similar, but when I use TabView the segmented control is not in the macOS Toolbar. Click here to see an example of what I would like

My current code is:

import SwiftUI

struct ContentView: View {
    var body: some View {
        TabView {
            Text("1")
                .tabItem {
                    Text("1")
            }
        }
    }
}

The result is here as an image

The segmented control needs to be in the toolbar and not the view.

Thank you.

like image 738
NG235 Avatar asked Oct 12 '19 03:10

NG235


Video Answer


1 Answers

I stumbled upon your question when I wanted to build something similar on macOS BigSur. I am using Xcode 12.2.

Here is what my solution would look like inspired by the answer from Asperi. It was important to set the title of the window group to an empty string "" otherwise it look weird.

Note that it only works when you run the app, not in the preview!

TabBar Example

App File

import SwiftUI

@main
struct SegmentedToolbarApp: App {
    var body: some Scene {
        WindowGroup("") {
            ToolbarItemPlacement()
        }
    }
}

ToolbarItemPlacement View

The important part was the placement with principal.

It was also important to set a bigger minWidth - otherwise the toolbar would disappear!

import SwiftUI

struct ToolbarItemPlacement: View {
    
    private let tabs = ["Watch Now", "Movies", "TV Shows", "Kids", "Library"]
    @State private var selectedTab = 0
    
    var body: some View {
        VStack {
            ChildTabView(title: self.tabs[self.selectedTab], index: self.selectedTab)
        }
        .toolbar {
            ToolbarItem(placement: .principal) {
                
                Picker("", selection: $selectedTab) {
                    ForEach(tabs.indices) { i in
                        Text(self.tabs[i]).tag(i)
                    }
                }
                .pickerStyle(SegmentedPickerStyle())
                .padding(.top, 8)
            }
        }
        .frame(minWidth: 800, minHeight: 400)
    }
}

ChildTabView

struct ChildTabView: View {
    var title: String
    var index: Int

    var body: some View {
        Text("\(title) - Index \(index)")
            .padding()
    }
}
like image 102
Denise Avatar answered Oct 02 '22 23:10

Denise