iOS 7 自定义 UINavigationBar TitleView 在推送或弹出新视图控制器时移动

iOS 7 Custom UINavigationBar TitleView moves when Pushing or Popping new View Controller

提问人:PhilBot 提问时间:5/4/2014 更新时间:2/16/2020 访问量:16542

问:

我正在使用带有以下代码的 UINavigationBar 的自定义标题视图:

// Set a label to the nav bar
THLabel *titleLabel = [[THLabel alloc] init];
titleLabel.text = @"Test";
titleLabel.font = [UIFont fontWithName:APP_FONT size:22.0];
titleLabel.frame = CGRectMake(0, 0, 100, 30);
titleLabel.textAlignment = NSTextAlignmentCenter;
titleLabel.textColor = CUSTOM_LIGHT_BLUE;
titleLabel.strokeColor = kStrokeColor;
titleLabel.strokeSize = kStrokeSize;
self.navigationItem.titleView = titleLabel;

问题在于,当呈现新的视图控制器,然后返回到原始视图控制器时,此自定义视图会移动,然后重新居中。请观看视频进行演示。

请在此处观看视频:https://www.youtube.com/watch?v=961CCVQmpJM&feature=youtu.be

我已经禁用了导航控制器的每个子视图的自动调整大小,包括每个视图控制器的情节提要和代码:

    // Set the navigation bar hidded on the log in view
    UINavigationController* mainViewController = (UINavigationController*)self.appDelegate.window.rootViewController;
    [mainViewController setNavigationBarHidden:YES];
    [[mainViewController navigationBar] setAutoresizesSubviews:NO];

但是,它仍然会调整大小!我怎样才能阻止这种情况 - 我做错了什么?谢谢!

iOS iPhone Objective-C UI导航栏 自动调整大小掩码

评论

1赞 Dima 5/5/2014
titleView 代码位于何处?您是否尝试过将其移动到 或 ?viewDidLoadinit
1赞 Barbara R 5/6/2014
我已经在我的应用程序中尝试了这部分代码(因为我没有 THLabel 类),一切都按预期工作,标题视图没有奇怪的移动:UILabel *titleLabel = [[UILabel alloc] init];titleLabel.text = @“测试”;titleLabel.font = [UIFont fontWithName:@“Bakersville” size:22.0];titleLabel.frame = CGRectMake(0, 0, 100, 30);titleLabel.textAlignment = NSTextAlignmentCenter;self.navigationItem.titleView = titleLabel;你能提供THLabel类的代码,这样我就可以检查一下我是否看到那里有什么问题?
0赞 PhilBot 5/7/2014
谢谢你的评论,芭芭拉。以下是托管 THLabel 的 Github 存储库:github.com/MuscleRumble/THLabel
0赞 PhilBot 5/9/2014
我将所有 THLabels 更改为 UILabels,但它仍然存在此问题。

答:

5赞 Rivera 5/14/2014 #1

我会将标签嵌入到 .Interface Builder不喜欢直接在 中输入,原因可能与您的问题有关。UIViewUILabeltitleView

同时尝试将 设置为 。根据我的经验,条形图中的任何自定义视图都以这种方式表现得更好。autoResizingMaskUIViewAutoresizingFlexibleTopMargin

评论

0赞 PhilBot 5/15/2014
我已经尝试了所有这些建议。我将 THLabel 添加到 UIView 中,并将其添加为 titleView,并更改了自动调整大小掩码......当我更改视图控制器时,它仍在移动。
0赞 Rivera 5/15/2014
使用没有自定义的常规呢?即使只是普通的黑色,也可以缩小可能的原因。UILabelUIView
0赞 Luke Smith 1/12/2015
按照建议设置 autoResizingMark 似乎已经解决了我的问题。我在标准视图中设置了一个 ImageView,作为 titleView。在 ViewDidLoad 中声明,并且在弹出视图时不断跳动。谢谢。
0赞 Mocha 2/13/2020
在视图中嵌入标签可以删除在推送和弹出 VC 时出现的奇怪动画(标签会放大和缩小)。
32赞 Alex Peda 5/17/2014 #2

只有当我将设置 titleView 代码放在 viewWillAppear 中时,它对我来说才是可重现的。将其移动到 viewDidLoad 可解决此问题

评论

0赞 Chris Prince 7/16/2014
请看下面我的答案。
0赞 Joe M 3/4/2016
哇!这解决了我的问题!我在viewWillLayoutSubviews中设置标题,在推送过程中,标题会卡在导航栏上
1赞 Chris Prince 7/16/2014 #3

扩展上面 @Alex Peda 的回答,我发现在 iOS7 上,在 viewDidLoad 之外,自定义标题似乎有一个最小标题宽度。这是我正在做的事情,如下所示。请注意,下面有一些方法特别适用于我的代码。

#define MAX_TITLE_WIDTH 400
#define MIN_TITLE_WIDTH 150

- (void) setNavBarTitle: (NSString *) newTitle;
{
    if (!newTitle) newTitle = @"";
    NSMutableString *title = [newTitle mutableCopy];

    if (![_titleView.text isEqualToString:title]) {

        NSAttributedString *attrTitle = [UIAppearance attributedString:title withFontType:FontTypeTitle | FontTypeBold | FontTypeItalic size: 40.0 andOtherAttributes:@{NSForegroundColorAttributeName: [UIColor blackColor]}];
        _titleView.attributedText = attrTitle;
        [_titleView sizeToFit];

        // In iOS7, if you set the nav bar title with a custom view outside of viewDidLoad, there appears to be a minimum title width. Narrower custom view titles are not centered properly. I'm working around this by centering the text in the label, and setting the width of the label to the minimum width.
        if ([Utilities ios7OrLater]) {
            if (_titleView.frameWidth < MIN_TITLE_WIDTH) {
                _titleView.textAlignment = NSTextAlignmentCenter;
                _titleView.frameWidth = MIN_TITLE_WIDTH;
            }
        }

        if (_titleView.frameWidth > MAX_TITLE_WIDTH) {
            _titleView.frameWidth = MAX_TITLE_WIDTH;
        }
    }

    self.navigationItem.titleView = _titleView;
}
1赞 hellorrr 11/29/2016 #4

这也发生在我身上。你可以做两件事:

1) 确保导航设置在 viewDidLayoutSubviews 或 viewDidLoad 中完成,如上述答案所述

2)我的左右栏按钮项为零,但仅在设置标题标签后才调用它们。在将 TitleLabel 设置为 TitleView 之前,请确保将左右栏按钮项设置为 nil(当然,如果您不使用它们)。

0赞 Michał Kwiecień 6/21/2017 #5

就我而言,发生这种情况是因为我在 titleView 之前设置了 UIBarButton。首先设置 titleView。现在工作得很好。

0赞 Alfonz 9/8/2017 #6

对我有用的是在视图控制器中创建一个变量来保存您想要的标题视图,然后在 中初始化它。然后,您可以将该视图设置为 in,它应该可以正确显示。无需设置 autoResizeMask 或 rightBarButtons 等。viewDidLoadself.navigationItem.titleViewviewWillAppear

例:

class ViewController {
    var myTitleImage: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()
        myTitleImage = UIImageView(frame: CGRect(x: 0, y: 0, width: 25, height: 25))
        myTitleImage.contentMode = .scaleAspectFit
        myTitleImage.image = #imageLiteral(resourceName: "my_title_image")
        // etc...
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        self.navigationItem.titleView = self.myTitleImage
    }    
}
0赞 Septronic 2/16/2020 #7

我尝试了上面的所有答案,最终创建了这样的视图和标签:

  1. 我为我的 VC 添加了一个变量:UIView

    let titleView: UIView = {
        // A factory method that returns a customised `UILabel`
        let label = Factory.Label.title() 
    
        let view = UIView()
        view.addSubview(label)
        label.text = localized.mainMenuItemSettings()
        //I use EasyPeasy for my constraints, 
        //but essentially I set top, left, bottom and right anchors to fill my UIView
        label.easy.layout(Edges()) 
        return view
    }()
    
  2. 然后在我的方法中,我将视图设置为我的:viewWillAppear(animated:)titleViewnavigationItem

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        navigationItem.titleView = titleView
    }
    

我使用EasyPeasy进行约束,因为我发现它们非常易于使用且非常紧凑。