How do I get a tab bar in iOS15 that looks like the one in iOS14?

I don't understand the changes made to the tab bar in iOS 15.

In my app, I have a collection view that goes all the way down to the bottom of the screen.

When the tab bar appears, it covers some of that collection view, which is fine.

However, in iOS15, the tab bar has no background (and no blur effect), thus making the tab bar item text hard to see over the collection view.

In interface builder, I tried turning on the "Scroll Edge" option. This gives a translucent background to the tab bar similar to what I had in iOS 14.

Unfortunately, the menu tab bar item text size is affected by this option. For some reason, it doesn't use the font size I set, but something smaller.

Why is this happening? How do I get it to use the correct font size?

P.S. I'm only using text for the tab bar items. There are no images.

  • Why can't I delete my comment :(

Add a Comment

Replies

The tab bar is meant to have a background until nothing is scrolled behind it. If the tab bar doesn’t respond to you scrolling away from the bottom by displaying its background, then we likely couldn’t find the scroll view (the default search makes a lot of assumptions for performance sake).

New in iOS 15, you can explicitly set the scroll view for your view controller with UIViewController.setContentScrollView(_:). This will likely resolve your overall issue.

That said, the appearances involved are controlled by the standardAppearance and scrollEdgeAppearance properties. Scroll edge values are used when we reach the edge of a scroll view (top for navigation bar, bottom for tool and tab). If you need more customization you can configure UITabBarAppearance instances for these cases. Setting both to the same values will effectively disable the transition (by displaying the same appearance at all times).

  • I'm experiencing this transparency issue on navigationBar. It is not present in all case. Some are always transparent unless one scrolls up the tableview inside, some are randomly ok (opaque) or ko (transparent) with no reliable cause. Calling setContentScrollView on the navigation controller with the contained tableview does not solve the issue

  • You don't call setContentScrollView() on the navigation controller, you call it on your view controller, typically when you setup the view hierarchy (such as in loadView() or viewDidLoad()).

  • What if one of the view controllers has no scroll view? In that case, a clear background is used in iOS 15 but what is the logic behind that? How should one decide whether to use a clear background when there is no scroll view?

OK. I've been able to get an opaque background by setting navigationBar.scrollEdgeAppearance to standardAppearance. Nevertheless I still can't understand why some navigation items default to opaque and other transparent.

Add a Comment

I have this issue in SwiftUI where the ScrollView is not the first view in my hierarchy. Is there another solution then make it the first view?

I'm seeing this in SwiftUI with Map inside of a TabView. Presumably because Map doesn't use a standard scroll view?

var body: some View {
    TabView {
        Map(coordinateRegion: $region)
            .ignoresSafeArea()
            .tabItem { Label("Map", systemImage: "map") }
    }
}

While I understand Rincewind's answer, it doesn't explain why iOS 15 lost the ability to consistently find the scroll view. I have made no changes in my hierarchy, and the app still targets an older SDK, however in iOS 14 the tab bars have a proper blur background, but in iOS 15 that is just gone. This strikes me more on the order of a bug, not a feature. This occurs on every scrolling screen in my app, which means it's failing for all kinds of hierarchies. And they're not tricky, e.g. here's one:

ZStack {
    VStack {
        // stuff
    }

    ScrollView(.vertical, showsIndicators: false) {
        // stuff
    }
}

Finally, the scrollEdgeApppearance that would fix this is not available unless you target iOS 15. Seems like a hellish catch-22.

This is my personal nightmare. I haven't done an app release for a couple of months simply because I cannot get tab bar appearances working correctly, and my apps rely on tabbars. I would love to use the default iOS 15 behaviour, except when switching between tabs the appearances are not reset - switching to tabs that don't contain a scrollview from tabs that do contain a scrollview sometimes there will be a non transparent tab bar and other times it will be correctly transparent. It flickers if you hover around the scroll edge on a scrollview. Just a nightmare. I can't even get consistent iOS 14 looking translucent all the time tabbars otherwise I would just revert. Things would be easier if I just targeted iOS 15, but funnily enough not all users use iOS 15 so I would go broke if I did that. I'm sure the excuse will be that I haven't coded my VC's in a fashion that are consistent with standards wrt tabbars and scrollviews and tabs without scrollviews but I just can't find what the standard should be - instead all I find is an internet full of hacky ugly fixes to revert behaviour :( #frustration

  • Until I work out what I have done wrong in my app to make the tab bar appearances not work correctly in iOS 15 I have gone live with the same solution as others involving setting an appearance with a neutral color and applying it to standardappearance and scrolledgeappearance. However, I very much look forward to removing this code as the iOS 15 default appearances particularly suit my apps and I will have to do more work to find out why the app does not pick whether it is at a scroll edge or not in every situation. :) #frustrationaverted

Add a Comment

Until it's fixed, you can use .edgesIgnoringSafeArea([.top, .leading, .trailing]) on any view that gets behind the tab bar!

Post not yet marked as solved Up vote reply of r8js Down vote reply of r8js

I have also been stuck on this for weeks, and was finally able to get it working with something like this:

if #available(iOS 13.0, *) {
   let tabBarAppearance: UITabBarAppearance = UITabBarAppearance()
   tabBarAppearance.configureWithDefaultBackground()
   if #available(iOS 15.0, *) {
      UITabBar.appearance().scrollEdgeAppearance = tabBarAppearance
   }
}

I have this set this in SceneDelegate.swift

Yay!  jpritchard9518's answer worked for me—had also been stuck on this for months.

if #available(iOS 15, *) {

 // For navigation Bar

let Nav_appearance = UINavigationBarAppearance()
      Nav_appearance.configureWithOpaqueBackground()
      Nav_appearance.backgroundColor = .systemYellow
      navigationController?.navigationBar.standardAppearance = Nav_appearance
      navigationController?.navigationBar.scrollEdgeAppearance = navigationController?.navigationBar.standardAppearance

       // For Tab bar controller

let Tab_appearance = UITabBarAppearance()
      Tab_appearance.configureWithOpaqueBackground()
      Tab_appearance.backgroundColor = .systemYellow
      tabBarController?.tabBar.standardAppearance = Tab_appearance
      tabBarController?.tabBar.scrollEdgeAppearance = Tab_appearance

       }