5

I am using a TabView to represent three tabs. In iOS 14, this is handled nicely, but iOS 13 results in a gray bottom bar which is the tab bar for navigation. How can I remove this bar?

Please bear in mind that this is a TabView within a TabView. The outer TabView's bar is shown at the bottom with five tabs; the inner TabView bar I do not want shown at all.

The code below represents the inner TabView.

import SwiftUI

struct DashboardView: View {
    @State private var pageIndex = 1
    
    var body: some View {
        VStack {
            DashboardTopBar(index: $pageIndex) // A custom selected tab indicator
            if #available(iOS 14.0, *) {
                TabView(selection: $pageIndex) {
                    RehabView().tag(0)
                    PerformanceView().tag(1)
                    RecoveryView().tag(2)
                }
                .tabViewStyle(PageTabViewStyle())
                .indexViewStyle(PageIndexViewStyle(backgroundDisplayMode: .always))
            } else {
                TabView(selection: $pageIndex) {
                    RehabView().tag(0)
                    PerformanceView().tag(1)
                    RecoveryView().tag(2)
                }
            }
        }
    }
}

The image below shows iOS 13 on the left and iOS 14 on the right.

Left: iOS 13, Right: iOS 14

Minimal, Complete, and Verifiable Example

If the code below is launched on iOS 13, you will note a tab bar on the bottom and an empty tab bar on top of it.

import SwiftUI

struct ContentView: View {
    @State private var outerTabViewSelectedTab = 0
    @State private var innerTabViewSelectedTab = 1
    var body: some View {
        TabView(selection: $outerTabViewSelectedTab,
                content:  {
                    Text("Outer 1").tabItem { Text("Outer 1") }.tag(1)
                    TabView(selection: $innerTabViewSelectedTab,
                            content:  {
                                Text("Inner 1").tag(1)
                                Text("Inner 2").tag(2)
                            }).tabItem { Text("Outer 2") }.tag(2)
                })
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
roadRunner
  • 173
  • 1
  • 23
McGuile
  • 818
  • 1
  • 11
  • 29
  • .indexViewStyle(PageIndexViewStyle(backgroundDisplayMode: .no)) – Dc7 Sep 22 '20 at 10:20
  • @Dc7 Unfortunately, `.indexViewStyle` and `PageIndexViewStyle` are only available in iOS 14. I am looking specifically for iOS 13. – McGuile Sep 22 '20 at 10:25
  • I think then, you have to create it with UIViewRepresentable!!! – Dc7 Sep 22 '20 at 10:27
  • Does this answer your question https://stackoverflow.com/a/62305094/12299030? – Asperi Sep 24 '20 at 15:15
  • @Asperi It doesn't, sorry. I attempted both `true` & `false` values for the translucency but the bar still remains. The other tabs contain list views and the bar overlaps the items. – McGuile Sep 25 '20 at 09:31
  • I could not reproduce this, so it is probably something in those your custom subviews, either in DashboardTopBar or internals of TabView. – Asperi Sep 25 '20 at 16:35
  • @Asperi I have added MCV example code to reproduce, as well as my hack solution as an answer. If you can improve it I'd accept your answer. – McGuile Sep 26 '20 at 10:48
  • Why are you adding that `TapView` if you don't want it to be visible? – Mojtaba Hosseini Sep 27 '20 at 07:23
  • @MojtabaHosseini So that in iOS 14 the swipe functionality of TabView is usable. – McGuile Sep 28 '20 at 07:48
  • So if it is only for iOS 14, why don't you get rid of it on iOS 13? – Mojtaba Hosseini Sep 28 '20 at 09:35
  • If the solution is simple using a TabView and a single property modifier then there is little benefit in creating more work than necessary by designing a custom tab view. – McGuile Sep 28 '20 at 09:38

1 Answers1

6

Hide it explicitly... as it is for backward compatibility it is safe, because behavior is already known and won't change.

So here is a solution

var body: some View {
    TabView(selection: $outerTabViewSelectedTab,
            content:  {
                Text("Outer 1").tabItem { Text("Outer 1") }.tag(1)
                TabView(selection: $innerTabViewSelectedTab,
                        content:  {
                            Text("Inner 1").tag(1)
                             .background(TabBarAccessor { tabBar in
                                tabBar.isHidden = true
                             })
                            Text("Inner 2").tag(2)
                        }).tabItem { Text("Outer 2") }.tag(2)
            })
}

Used TabBarAccessor from my other solution in https://stackoverflow.com/a/59972635/12299030

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Asperi
  • 228,894
  • 20
  • 464
  • 690
  • 1
    Great! And of course, for those wondering, the `.background` modifier would need to be applied to all tabs that wish to hide the tab bar. Thanks. – McGuile Oct 01 '20 at 12:00