Search code examples
iosuinavigationcontrolleruiimageviewuistackviewviewwillappear

UIStackView on TitleView Spacing issue after iOS 16


I have an UIStackView set up on the title view of the navigation bar in my app. It simply shows the icon of the app to the left of the title. In iOS 15 and earlier, this displayed fine. Right now, however, it shows fine the first time you launch the app, but navigating to a different view, the icon is in the wrong spot of THAT view, and will be in the incorrect spot when returning to the parent view as well. Pictures of this are below the code.

- (void)viewWillAppear:(BOOL)animated
 UIImageView *theimageView = [[UIImageView alloc] init];
    theimageView.contentMode = UIViewContentModeScaleAspectFit;
    theimageView.image = [UIImage imageNamed:nameOfColor];
    UILabel *titleLabel = [[UILabel alloc] init];
    titleLabel.font = [UIFont fontWithName:@"Roboto-Bold" size:16];
    titleLabel.textColor = [UIColor whiteColor];
    titleLabel.text = self.title;

    UIStackView *hStack = [[UIStackView alloc] init];
    [hStack addArrangedSubview:theimageView];
    [hStack addArrangedSubview:titleLabel];
    hStack.axis = UILayoutConstraintAxisHorizontal;

 
    self.navigationItem.titleView = hStack;
    [super viewWillAppear:animated];

enter image description here enter image description here


Solution

  • I'm able to reproduce your issue. One thing I'm sure of is that apple has made some changes to this part of UIKit. enter image description here

    Providing a custom UIStackView as a titleView to the navigation bar is totally OK. But to properly set a UIStackView you should add some constraints.

    You should add several constraints to help the UIStackView know how you want to layout your arranged subview.

    UIImageView *theimageView = [[UIImageView alloc] init];
    theimageView.contentMode = UIViewContentModeScaleAspectFit;
    theimageView.image = [UIImage systemImageNamed: @"peacesign"];
    
    //  Contraints to image height
    [theimageView.heightAnchor constraintEqualToConstant: 20].active = true;
    
    
    UILabel *titleLabel = [[UILabel alloc] init];
    titleLabel.font = [UIFont fontWithName:@"Roboto-Bold" size:16];
    titleLabel.textColor = [UIColor blackColor];
    titleLabel.text = self.title;
    //  Contraints to label height
    [titleLabel.heightAnchor constraintEqualToConstant: 20].active = true;
    
    
    UIStackView *hStack = [[UIStackView alloc] init];
    [hStack addArrangedSubview:theimageView];
    [hStack addArrangedSubview:titleLabel];
    hStack.axis = UILayoutConstraintAxisHorizontal;
    //  Center the items
    hStack.alignment = UIStackViewAlignmentCenter;
    
    //  Spacing of 6
    hStack.spacing = 6;
    
    
    
    self.navigationItem.titleView = hStack;
    [super viewWillAppear:animated];
    

    If you add the two missing constraints, now the titleView works like iOS 15 and earlier.

    enter image description here