1

I am learning TabView and have a requirement where my main/content view will display map and will have TabView at the bottom. Whenever any of the tab's on TabView is tapped, a custom modal sheet (with slider handle to adjust sizes... more like bottom sheet) will be opened. Whenever I slide the modal down completely or close the modal sheet, the selected tab on tabview should get de-selected i.e. no tabs on the TabView should be selected by default.

Is this achievable with SwiftUI TabView? I am noticing first tab is always selected by default. Or will I have to create a custom tab view to achieve this?

Code:

import SwiftUI
import Foundation

struct ContentView: View {
    
    var body: some View {
        VStack {
            SimpleDataView()
            BottomTabView()
        }
    }
}

struct SimpleDataView: View {    
    var body: some View {
        VStack {
            Text("Map will be displayed over here").background(Color.gray).frame(maxWidth: .infinity, maxHeight: .infinity)
            Spacer()
        }
        .background(Color.gray)
        .ignoresSafeArea()
    }
}

struct BottomTabView: View {
    @State var selection: Int = -4
    var body: some View {
        TabView(selection: $selection) {
            Group {
                /// Custom modal view with slider handle/bottom sheet will be displayed.
                Text("Home tab's view")
                    .tabItem {
                        Label("Home", systemImage: "house")
                    }
                    .tag(0)
                    .frame(height: 100.0)
                Text("Search tab's view")
                    .tabItem {
                        Label("Search", systemImage: "magnifyingglass")
                    }
                    .tag(1)
                    .frame(height: 100.0)
            }
        }.onAppear {
            UITabBar.appearance().backgroundColor = .lightGray
        }
    }
}

To keep the code short and simple, I am using Text() element in my BottomTabView struct for now, but it will be replaced with CustomModalSheet which when closed, so de-select the selected tab on tab view and no tabs should be selected by default.

2
  • I don't think this is possible with the built-in TabView. Perhaps take a look at my answer here for how to create your own tab view. Commented Jul 8, 2023 at 2:46
  • 1
    Yes, the default behavior of TabView is to have a selected tab when it first appears, You have to find another way i.e. @Sweeper suggested or any other way. But using Tabview it's not possible I believe. Commented Jul 8, 2023 at 2:58

1 Answer 1

0

Use this custom tab bar, and onDismiss sheet, set nil to the selectedTab. You can modify code as per your needs

Custom TabBar Item:

struct TabBarItem: View {
let title: String
let imageName: String
let tag: Int
@Binding var selectedTab: Int?

var body: some View {
    
    Button {
        selectedTab = selectedTab == tag ? nil : tag
    } label: {
        VStack(spacing: 4) {
            Image(systemName: imageName)
            Text(title)
        }
        .foregroundColor(selectedTab == tag ? .blue : .gray)
    }
  }
}

TabBar

struct TabBar: View {
@Binding var selectedTab: Int?

var body: some View {
    HStack {
        Spacer()
        TabBarItem(title: "Home", imageName: "house", tag: 0, selectedTab: $selectedTab)
        Spacer()
        TabBarItem(title: "Search", imageName: "magnifyingglass", tag: 1, selectedTab: $selectedTab)
        Spacer()
    }
  }
}

TabBar Container

struct BottomTabView: View {

@Binding var selectedTab: Int?

var body: some View {
    
    TabBar(selectedTab: $selectedTab)
        .padding(10)
        .background(Color.gray.opacity(0.1))
    
    }
}

Usage

struct ContentView: View {
@State private var isModalVisible = false
@State private var selectedTab: Int? = nil

var body: some View {
    VStack {
        
        Spacer()

        Button {
            isModalVisible = true
        } label: {
            Text("Present sheet")
        }

        Spacer()
    }
    .safeAreaInset(edge: .bottom) {
        BottomTabView(selectedTab: $selectedTab)
    }
    .sheet(isPresented: $isModalVisible, onDismiss: {
        selectedTab = nil
    }) {
        // Present your custom modal sheet here
        CustomModalSheet()
    }
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

This works but I was the custom modal sheet to be behind the tab bar i.e. with this solution it covers the tab bar.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.