Is this new navigation bar behaviour in xcode 11 beta a bug or intended?
Asked Answered
H

2

9

I noticed after compiling one of my apps in Xcode 11 beta, that navigation bars have no background when prefersLargeTitles is set. Is this intended behavior?

I noticed this is how the messages app works now when scrolling down and a large title is visible there is no nav bar background.

Here is the code used to set up the navBar attributes:

 override func viewWillAppear(_ animated: Bool) {
    let textAttributes = [NSAttributedString.Key.foregroundColor:ThemeManager.shared.default1]
    self.navigationController?.navigationBar.largeTitleTextAttributes = textAttributes
    self.navigationController?.navigationBar.titleTextAttributes = textAttributes
    self.navigationController?.navigationBar.tintColor = ThemeManager.shared.default1
 self.navigationController?.setNavigationBarHidden(false, animated: true)
    self.navigationController?.navigationBar.prefersLargeTitles = true
    let nav = self.navigationItem
    nav.title = "My Profile"
}

Here are a couple of images showing the difference:

left, compiled on Xcode 10, right, Xcode 11 beta:

enter image description here enter image description here

Once you scroll up on the 11 Beta version, the background fades back in. Note that apps that are not compiled in Xcode 11 beta will still behave in the normal way, only changes after compiling for some reason. Is this intended, and how would I bring back the original behavior?

Headroom answered 6/6, 2019 at 18:7 Comment(6)
Is this difference on the same app running on the same device or is one on iOS 13 and the other on iOS 12 (or earlier)?Vick
One on my physical device with iOS 13 and the other is on ios 12 simulator. But I have another app on my iOS 13 device which handles the navigation bar in the exact same way (same code) and that works like normal on my iOS 13 device, i suspect if i compile that app on Xcode 11 it will change.Headroom
@Vick Just tested, my other app was working fine on ios 13 devices, compiled the code on Xcode 11 and the navbar background has vanished.Headroom
Likely intended by Apple. Just set a blurry background for your navigation bar if you want to keep the old behavior. (by blurry, I mean a setBackgroundImage with an image made with a partially transparent color). And don't forget shadowImage.Sakai
Cœur, given this site, it would be nicer to post code with the solution than "do this and do that".Judicious
His stackoverflow.com/questions/58427943/… Can you pls check this I have same issue but none of the solution is working for meMargoriemargot
J
13

This is intended behavior for iOS 13.

Apple's idea (terrible in my opinion) is that the title should merge with the content to show that it is related. Once you start scrolling, when content goes behind the title bar then the title bar will take the "correct" appearance.

The reason this is terrible is because everyone has currently planned all of their UI without this behavior. So the new behavior should be opt-in instead of forcing everyone to opt-out (i.e. the change breaks everyone's code and if you're going to break everyone's code at least you should be clear about how to keep the tried and true behavior of the last 10 years).

As in your case, the result looks horrible. The result looks horrible in my case too.

Apple doesn't give answers but says that you should be using

- scrollEdgeAppearance

From UINavigationBar in order to control the appearance of the bar when content is aligned top-of-content to bottom-of-navbar ... in my case this method returns nil though so I'm currently unsure how we're supposed to use this.

This seems to be discussed here as well:

New UINavigationBar appearance in detail pane of UISplitViewController in iOS 13

So the current workaround would seem to be this in your view controller:

- (void)viewDidLoad;
{
    [super viewDidLoad];
    if (@available(iOS 13,*)){
        UINavigationBar *bar =self.navigationController.navigationBar;
        bar.scrollEdgeAppearance = bar.standardAppearance;
    }
}

It works, but if it's the intended approach, I don't know...

EDIT:

Doing this does seem to block any additional direct customization to the UINavigationBar as has been noted. Possible that adjusting the scrollEdgeAppearance from here is the way to go. Ugly. Ugly. Ugly.

EDIT: Progress... this is working now for managing the background. You need to call this instead of setting barTint directly.

@interface UINavigationBar (Compatibility)
- (void)setCompatibleTint:(UIColor *)fg andBarTint:(UIColor *)bg;
@end

@implementation UINavigationBar (Compatibility)
- (void)setCompatibleTint:(UIColor *)fg andBarTint:(UIColor *)bg;
{
    self.tintColor = fg;
    self.barTintColor = bg;
    if (@available(iOS 13,*)){
        // we need to tell it to adopt old style behavior first
        UINavigationBarAppearance *appearance = self.standardAppearance;
        appearance.backgroundColor = bg;
        NSDictionary *attributes = self.titleTextAttributes;
        appearance.titleTextAttributes = attributes;
        attributes = self.largeTitleTextAttributes;
        appearance.largeTitleTextAttributes = attributes;
        self.scrollEdgeAppearance = appearance;
        self.standardAppearance = appearance;
        self.compactAppearance = appearance;
    }
}
@end

I'm not entirely sure yet on the text attributes but it seems to flow from the background color. It's a complete PITA.

It would be nicer to set this as a subclass and override barTint but of course a lot of the UIKit objects create these bars themselves so you won't get the subclass.

Judicious answered 21/6, 2019 at 4:43 Comment(2)
Thank you, It works, but I noticed that my textattributes I set don't work, so I can't change the title color from the default black!Headroom
I have the same problem now, I got this working for me last night, and now find I can't change the colors either. Maybe navBar.scrollEdgeAppearance.backgroundColor and navBar.scrollEdgeAppearance.titleTextAttributes are the things that need to be adjusted now. Seems like a really stupid thing so far.Judicious
H
7

Swift version of dbquarrel's solution.

First declare your textAttributes:

let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.red]

Use these in a UINavigationBarAppearance() to enable you to change the colour of the text in 3 different modes (scollEdge, standard and compact).

override func viewDidLoad() {
    super.viewDidLoad()
    if #available(iOS 13.0, *) {
        let appearance = UINavigationBarAppearance()
        appearance.largeTitleTextAttributes = textAttributes
        appearance.titleTextAttributes = textAttributes
        let bar = self.navigationController?.navigationBar
        bar?.scrollEdgeAppearance = appearance
        bar?.standardAppearance = appearance
        bar?.compactAppearance = appearance
    } else {
        // Fallback on earlier versions
    }
}
Headroom answered 21/6, 2019 at 15:23 Comment(2)
The Peter Rupert solution only works for me if I scroll down the viewOrlosky
@Orlosky updated answer to add more detail and hopefully fix that issue.Headroom

© 2022 - 2024 — McMap. All rights reserved.