ios UINavigationItem 居中标题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8258879/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 15:34:37  来源:igfitidea点击:

UINavigationItem centering the title

iphoneiosuinavigationcontrolleruinavigationitem

提问by Neelesh

I have a navigationBar with both Left and Right bar buttons on each side. I have a customTitlelabelwhich I set as the titleView of the UINavigationItem.

我有一个带有左右栏按钮的导航栏。我有一个customTitlelabel我设置为UINavigationItem.

[self.navigationItem setTitleView:customTitleLabel];

[self.navigationItem setTitleView:customTitleLabel];

All is fine now. The problem, the size of the rightbarButton is dynamic based on the input I get in one of the text fields.

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

Therefore the title is automatically centered based on the available space between the buttons.

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

how can i set the title to a fixed position?

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

采纳答案by occulus

You can't do what you want directly -- the position of your title view is out of your control (when managed by UINavigationBar).

你不能直接做你想做的——你的标题视图的位置不受你的控制(当由 管理时UINavigationBar)。

However, there are at least two strategies to get the effect you want:

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

1) Add the title view not as the 'proper' title view of the nav bar, but as a subview of the UINavigationBar. (Note: this is not 'officially' sanctioned, but I've seen it done, and work. Obviously you have to watch out for your title label overwriting bits of the buttons, and handle different size nav bars for different orientations, etc. -- a bit fiddly.)

1) 添加标题视图不是作为导航栏的“正确”标题视图,而是作为UINavigationBar. (注意:这不是“官方”批准的,但我已经看到它完成并工作。显然你必须注意你的标题标签覆盖按钮的位,并处理不同方向的不同大小的导航栏等。 ——有点啰嗦。)

2) Make an intelligent UIView subclass that displays a given subview (which would be your UILabel) at a position calculated to effectively show the subview perfectly centered on the screen. In order to do this, your intelligent UIView subclass would respond to layout events (or frameproperty changes etc.) by changing the position (frame) of the label subview.

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

Personally, I like the idea of approach 2) the best.

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

回答by followben

Setting the titleView property of the nav bar works just fine - no need to subclass or alter any frames other than those of your custom view.

设置导航栏的 titleView 属性工作正常 - 除了自定义视图的框架之外,无需子类化或更改任何框架。

The trick to getting it centered relative to the overall width of UINavigationBar is to:

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

  1. set the width of your view according to the size of the text
  2. set the alignment to centered and
  3. set the autoresizingmask so it gets resized to the available space
  1. 根据文本的大小设置视图的宽度
  2. 将对齐设置为居中并
  3. 设置 autoresizingmask 使其调整到可用空间

Here's some example code that creates a custom titleView with a label which remains centred in UINavigationBar irrespective of orientation, left or right barbutton width:

下面是一些示例代码,它创建一个带有标签的自定义 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;

回答by neoneye

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

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

回答by Ben Sinclair

The right answer is to override sizeThatFits:of your custom titleViewand return its content size. Navigation bar centers custom title view until it has no space left to do that.

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

For example if you have UIViewcontainer with UILabelinside:

例如,如果您有内部的UIView容器UILabel

@interface CustomTitleView : UIView

@property UILabel* textLabel;

@end

@implementation CustomTitleView

- (CGSize)sizeThatFits:(CGSize)size {
    CGSize textSize = [self.textLabel sizeThatFits:size];
    CGSize contentSize = size;
    contentSize.width = MIN( size.width, textSize.width );

    return contentSize;
}

@end

回答by Nicolas Miari

I tried aopsfan's answer but it didn't work. A breakpoint revealed that the bar's center was "(480.0, 22.0)" (The X coordinate way off) .

我尝试了 aopsfan 的回答,但没有用。断点显示条形的中心是 "(480.0, 22.0)" (X 坐标偏离)。

So I changed it into this:

所以我把它改成了这样:

- (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)

}

...and it works like a charm. The slide/fade effect when pushing view controllers is intact. (iOS 5.0)

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

回答by Nevin Chen

I had similar problem. enter image description hereMy solution is do hide the original back button, add add your own implementation. Since the system will reserve space for the left items.

我有类似的问题。 在此处输入图片说明我的解决方案是隐藏原来的后退按钮,添加添加您自己的实现。因为系统会为剩下的物品保留空间。

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

and the selector is simple

选择器很简单

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

now it looks like this: enter image description here

现在它看起来像这样: 在此处输入图片说明

oh...and don't forget to use autolayout in your custom title view if you have dynamic length content like label in it. I add an additional layout in the customview to give it like "wrap_content" in Android by setting it centered to parent , and leading and trailing space ">=" 0

哦...如果您有动态长度内容(如标签),请不要忘记在自定义标题视图中使用自动布局。我在 customview 中添加了一个额外的布局,通过将它设置为以 parent 为中心,并在前导和尾随空间 ">=" 0

enter image description here

在此处输入图片说明

回答by Richard H Fung

I had a similar situation where a titleViewshould be centered in UINavigationBar. I like occulus's approach of subclassing a UIView and overriding setFrame:. Then, I can center the frame inside the dimensions of UINavigationBar.

我有一个类似的情况,atitleView应该以 UINavigationBar 为中心。我喜欢 occulus 将 UIView 子类化并覆盖setFrame:. 然后,我可以在 UINavigationBar 的维度内将框架居中。

In the UIView subclass:

在 UIView 子类中:

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

The UIView subclass can then be assigned normally to titleViewfor each navigationItem. The developer does not have to programmatically add and remove special subviews from UINavigationBar.

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