UINavigationItem以标题为中心

时间:2011-11-24 14:49:35

标签: iphone ios uinavigationcontroller uinavigationitem

我有一个导航栏,每侧都有左右两个按钮。我有一个customTitlelabel,我将其设置为UINavigationItem的titleView。

  

[self.navigationItem setTitleView:customTitleLabel];

一切都很好。问题是,rightbarButton的大小是动态的,基于我在其中一个文本字段中得到的输入。

因此,标题会根据按钮之间的可用空间自动居中。

如何将标题设置为固定位置?

7 个答案:

答案 0 :(得分:28)

设置导航栏的titleView属性可以正常工作 - 无需子类化或更改自定义视图以外的任何帧。

让它相对于UINavigationBar的整体宽度居中的技巧是:

  1. 根据文字大小设置视图的宽度
  2. 将对齐设置为居中和
  3. 设置autoresizingmask,使其调整为可用空间
  4. 下面是一些示例代码,它创建一个带有标签的自定义titleView,该标签​​在UINavigationBar中保持居中,无论方向,左侧或右侧条形图宽度如何:

    self.title = @"My Centered Nav Title";
    
    // Init views with rects with height and y pos
    CGFloat titleHeight = self.navigationController.navigationBar.frame.size.height;
    UIView *titleView = [[UIView alloc] initWithFrame:CGRectZero];
    UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
    
    // Set font for sizing width
    titleLabel.font = [UIFont boldSystemFontOfSize:20.f];
    
    // Set the width of the views according to the text size
    CGFloat desiredWidth = [self.title sizeWithFont:titleLabel.font
                                constrainedToSize:CGSizeMake([[UIScreen mainScreen] applicationFrame].size.width, titleLabel.frame.size.height)
                                    lineBreakMode:UILineBreakModeCharacterWrap].width;
    
    CGRect frame;
    
    frame = titleLabel.frame;
    frame.size.height = titleHeight;
    frame.size.width = desiredWidth;
    titleLabel.frame = frame;
    
    frame = titleView.frame;
    frame.size.height = titleHeight;
    frame.size.width = desiredWidth;
    titleView.frame = frame;
    
    // Ensure text is on one line, centered and truncates if the bounds are restricted
    titleLabel.numberOfLines = 1;
    titleLabel.lineBreakMode = UILineBreakModeTailTruncation;
    titleLabel.textAlignment = NSTextAlignmentCenter;
    
    // Use autoresizing to restrict the bounds to the area that the titleview allows
    titleView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
    titleView.autoresizesSubviews = YES;
    titleLabel.autoresizingMask = titleView.autoresizingMask;
    
    // Set the text
    titleLabel.text = self.title;
    
    // Add as the nav bar's titleview
    [titleView addSubview:titleLabel];
    self.navigationItem.titleView = titleView;
    

答案 1 :(得分:15)

您无法直接执行所需内容 - 标题视图的位置超出您的控制范围(由UINavigationBar管理时)。

但是,至少有两种策略可以达到你想要的效果:

1)将标题视图添加为导航栏的“正确”标题视图,但作为UINavigationBar的子视图。 (注意:这不是'正式'批准,但我已经看到它完成了,并且工作。显然你必须注意你的标题标签覆盖按钮的位,并处理不同方向的不同尺寸的导航条等。 - 有点繁琐。)

2)制作一个智能的UIView子类,在一个计算的位置显示一个给定的子视图(可能是你的UILabel),以有效地显示子视图完全居中在屏幕上。为此,您的智能UIView子类将通过更改标签子视图的位置(frame)来响应布局事件(或frame属性更改等)。

就个人而言,我最喜欢方法2)的想法。

答案 2 :(得分:12)

override func viewDidLoad() {
    super.viewDidLoad()
    navigationController?.navigationBar.topItem?.title = ""
}

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    navigationItem.title = "Make peace soon"
}

答案 3 :(得分:3)

正确的答案是覆盖自定义sizeThatFits:的{​​{1}}并返回其内容大小。导航栏将自定义标题视图居中,直到它没有空间来执行此操作。

例如,如果您的titleView容器内有UIView

UILabel

答案 4 :(得分:2)

我尝试了aopsfan的答案,但它没有用。断点显示酒吧的中心是“(480.0,22.0)”(X坐标方式关闭)。

所以我把它改成了这个:

- (void)layoutSubviews 
{
    [super layoutSubviews];

    // Center Title View

    UINavigationItem* item = [self topItem]; // (Current navigation item)

    [item.titleView setCenter:CGPointMake(160.0, 22.0)]; 
    // (...Hard-coded; Assuming portrait iPhone/iPod touch)

}

......它就像一个魅力。推动视图控制器时的滑动/淡入淡出效果完好无损。 (iOS 5.0)

答案 5 :(得分:1)

我有类似的问题。 enter image description here 我的解决方案是隐藏原始的后退按钮,添加添加自己的实现。由于系统将为左侧物品预留空间。

UIImage* cancelIcon = [UIImage imageNamed:@"ic_clear"];
UIBarButtonItem* cancelButton = [[UIBarButtonItem alloc] initWithImage:cancelIcon style:UIBarButtonItemStylePlain target:self action:@selector(back:)];

,选择器很简单

- (void)back:(UIButton *) sender
{
    [self.navigationController popViewControllerAnimated:YES];
}

现在它看起来像这样: enter image description here

哦...如果你有像标签一样的动态长度内容,请不要忘记在自定义标题视图中使用自动布局。我在customview中添加了一个额外的布局,以便像#34; wrap_content"在Android中,通过将其设置为父级,以及前导和尾随空格"> =" 0

enter image description here

答案 6 :(得分:0)

我有类似的情况,titleView应该在UINavigationBar中居中。我喜欢occulus的子类化UIView并覆盖setFrame:的方法。然后,我可以将框架置于UINavigationBar维度的中心。

在UIView子类中:

-(void)setFrame:(CGRect)frame{
  super.frame = CGRectMake(320 / 2 - 50, 44 / 2 - 15, 100, 30);
}

然后可以为每个navigationItem将UIView子类正常分配给titleView。开发人员不必以编程方式添加和删除UINavigationBar中的特殊子视图。