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

时间:2014-05-03 23:51:30

标签: ios iphone objective-c uinavigationbar autoresizingmask

我正在使用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];

然而它仍然调整大小!我怎么能阻止这个 - 我做错了什么?谢谢!

7 个答案:

答案 0 :(得分:33)

只有在 viewWillAppear 中设置 titleView 代码时,它才能重现。将其移至 viewDidLoad 可解决问题

答案 1 :(得分:4)

我会将标签嵌入UIView内。由于某些可能与您的问题相关的原因,Interface Builder不会直接在UILabel中放置titleView

还尝试将autoResizingMask设置为UIViewAutoresizingFlexibleTopMargin。根据我的经验,任何酒吧中的自定义视图都表现得更好。

答案 2 :(得分:1)

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

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

2)我的左右栏按钮项目为nil,但只在设置了标题标签后才调用它们。在将titlelabel设置为titleview之前,请确保将右侧和左侧栏按钮项设置为nil(如果您当然没有使用它们)。

答案 3 :(得分:0)

扩展@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;
}

答案 4 :(得分:0)

在我的情况下,它发生是因为我在titleView之前设置了UIBarButton。设置titleView应该是第一个。现在工作得很好。

答案 5 :(得分:0)

对我来说有用的是在视图控制器中创建一个包含所需标题视图的变量,然后在viewDidLoad中对其进行初始化。然后,您可以将该视图设置为self.navigationItem.titleView中的viewWillAppear,并且应该正确显示。无需设置autoResizeMask,或rightBarButtons等。

示例:

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
    }    
}

答案 6 :(得分:0)

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

  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:)方法中,将视图设置为titleView的{​​{1}}:

    navigationItem

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