提问人:PhilBot 提问时间:5/4/2014 更新时间:2/16/2020 访问量:16542
iOS 7 自定义 UINavigationBar TitleView 在推送或弹出新视图控制器时移动
iOS 7 Custom UINavigationBar TitleView moves when Pushing or Popping new View Controller
问:
我正在使用带有以下代码的 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];
但是,它仍然会调整大小!我怎样才能阻止这种情况 - 我做错了什么?谢谢!
答:
我会将标签嵌入到 .Interface Builder不喜欢直接在 中输入,原因可能与您的问题有关。UIView
UILabel
titleView
同时尝试将 设置为 。根据我的经验,条形图中的任何自定义视图都以这种方式表现得更好。autoResizingMask
UIViewAutoresizingFlexibleTopMargin
评论
UILabel
UIView
只有当我将设置 titleView 代码放在 viewWillAppear 中时,它对我来说才是可重现的。将其移动到 viewDidLoad 可解决此问题
评论
扩展上面 @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) 确保导航设置在 viewDidLayoutSubviews 或 viewDidLoad 中完成,如上述答案所述
2)我的左右栏按钮项为零,但仅在设置标题标签后才调用它们。在将 TitleLabel 设置为 TitleView 之前,请确保将左右栏按钮项设置为 nil(当然,如果您不使用它们)。
就我而言,发生这种情况是因为我在 titleView 之前设置了 UIBarButton。首先设置 titleView。现在工作得很好。
对我有用的是在视图控制器中创建一个变量来保存您想要的标题视图,然后在 中初始化它。然后,您可以将该视图设置为 in,它应该可以正确显示。无需设置 autoResizeMask 或 rightBarButtons 等。viewDidLoad
self.navigationItem.titleView
viewWillAppear
例:
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
}
}
我尝试了上面的所有答案,最终创建了这样的视图和标签:
我为我的 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 }()
然后在我的方法中,我将视图设置为我的:
viewWillAppear(animated:)
titleView
navigationItem
override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) navigationItem.titleView = titleView }
我使用EasyPeasy进行约束,因为我发现它们非常易于使用且非常紧凑。
评论
viewDidLoad
init