Disable item in TabView SwiftUI
Asked Answered
S

3

5

How Can I set an item to disabled (not clickable) but visible in my tabView ?

TabView(selection: $selectedTab) {
            Settings()
                .tabItem {
                    Image(systemName: "gearshape.fill")
                    Text("Settings")
                }.tag(1)
                 .disabled(true) // Not Working
          
Studbook answered 7/11, 2020 at 11:21 Comment(0)
P
5

I just create a way to do what you want fully supported and customisable!

test with Xcode Version 12.1, iOS 14.1, Here goes:

    import SwiftUI

struct ContentView: View {
    

    @State private var selection = 0
    @State private var exSelection = 0
    private var disableThis = 2
    
    
    
    var body: some View
    {
        TabView(selection: $selection)
        {
            viewFinder(selectedIndex: selection == disableThis ? $exSelection : $selection)
                .tabItem { Image(systemName: "1.circle") }
                .tag(0)
            
            
            viewFinder(selectedIndex: selection == disableThis ? $exSelection : $selection)
                .tabItem { Image(systemName: "2.circle") }
                .tag(1)
            
            viewFinder(selectedIndex: selection == disableThis ? $exSelection : $selection)
                .tabItem { Image(systemName: "3.circle") }
                .tag(2)
            
            viewFinder(selectedIndex: selection == disableThis ? $exSelection : $selection)
                .tabItem { Image(systemName: "4.circle") }
                .tag(3)
        }
        .onAppear()
        {
            UITabBar.appearance().barTintColor = .white
        }
        .accentColor(selection == disableThis ? Color.gray : Color.red)
        .onChange(of: selection) { _ in
            if selection != disableThis { exSelection = selection } else { selection = exSelection }
        }
        
        
    }
    
    
    
}





struct viewFinder: View
{
    
    @Binding var selectedIndex: Int
    
    var body: some View {
        
        
        return Group
        {
            if      selectedIndex == 0
            {
                FirstView()
            }
            else if selectedIndex == 1
            {
                SecondView()
            }
            else if selectedIndex == 2
            {
                ThirdView()
            }
            else if selectedIndex == 3
            {
                FourthView()
            }
            else
            {
                EmptyView()
            }
        }
        

        
    }
    
}


struct FirstView: View { var body: some View {Text("FirstView")}}
struct SecondView: View { var body: some View {Text("SecondView")}}
struct ThirdView: View { var body: some View {Text("ThirdView")}}
struct FourthView: View { var body: some View {Text("FourthView")}}

enter image description here

Phantasm answered 7/11, 2020 at 13:28 Comment(2)
Error : Thread 1: EXC_BAD_ACCESS (code=1, address=0xa3a3a3a3a3a3a3ab) don't understand what it means...Seeder
Version 12.1 (12A7403)Seeder
S
1

There is not direct SwiftUI instrument for this now (SwiftUI 2.0), so find below possible approach based on TabBarAccessor from my another answer https://mcmap.net/q/957021/-programmatically-detect-tab-bar-or-tabview-height-in-swiftui.

Tested with Xcode 12.1 / iOS 14.1 (note - tint color changed just for demo because disabled item is grey and invisible on grey tabbar)

demo

struct TestTabBar: View {
    init() {
        UITabBar.appearance().unselectedItemTintColor = UIColor.green
    }
    @State private var selection = 0
    var body: some View {
        TabView(selection: $selection) {
            Text("First View")
                .background(TabBarAccessor { tabBar in
                    tabBar.items?.last?.isEnabled = false     // << here !!
                })
                .tabItem { Image(systemName: "1.circle") }
                .tag(0)
            Text("Second View")
                .tabItem { Image(systemName: "2.circle") }
                .tag(1)
        }
    }
}
Staphyloplasty answered 7/11, 2020 at 12:20 Comment(3)
I have this error : "Return from initializer without initializing all stored properties" trying to solve itSeeder
And if I copy paste your code, I have this message : "Cannot find 'TabBarAccessor' in scope"Seeder
I gave link for that - read carefully from beginning.Staphyloplasty
A
0

Updated above code to disable multiple tabs

struct ContentView: View {
    
    
    @State private var selection = 0
    @State private var exSelection = 0
    private var disableThis = [2, 3]
    
    
    
    var body: some View
    {
        TabView(selection: $selection)
        {
            viewFinder(selectedIndex: disableThis.contains(selection) ? $exSelection : $selection)
                .tabItem { Image(systemName: "1.circle") }
                .tag(0)
            
            
            viewFinder(selectedIndex: disableThis.contains(selection) ? $exSelection : $selection)
                .tabItem { Image(systemName: "2.circle") }
                .tag(1)
            
            viewFinder(selectedIndex: disableThis.contains(selection) ? $exSelection : $selection)
                .tabItem { Image(systemName: "3.circle") }
                .tag(2)
            
            viewFinder(selectedIndex: disableThis.contains(selection) ? $exSelection : $selection)
                .tabItem { Image(systemName: "4.circle") }
                .tag(3)
        }
        .onAppear()
        {
            UITabBar.appearance().barTintColor = .white
        }
        .accentColor(disableThis.contains(selection) ? Color.gray : Color.red)
        .onChange(of: selection) { _ in
            if !disableThis.contains(selection) { exSelection = selection } else { selection = exSelection }
        }
        
        
    }  
}
Appropriation answered 28/9, 2023 at 20:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.