是否有一种直接的方法来覆盖导航控制器中导航栏中当前导航栏项目的titleView?我已经尝试创建一个新的UIView并用我自己的UIVIew替换topView的titleView属性但没有成功 .
基本上,我想要导航栏 Headers 的多行 Headers . 有什么建议?
设置 UINavigationItem 的 titleView 属性 . 例如,在视图控制器的 viewDidLoad 方法中,您可以执行以下操作:
UINavigationItem
titleView
viewDidLoad
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 480, 44)]; label.backgroundColor = [UIColor clearColor]; label.numberOfLines = 2; label.font = [UIFont boldSystemFontOfSize: 14.0f]; label.shadowColor = [UIColor colorWithWhite:0.0 alpha:0.5]; label.textAlignment = UITextAlignmentCenter; label.textColor = [UIColor whiteColor]; label.text = @"This is a\nmultiline string"; self.navigationItem.titleView = label; #if !__has_feature(objc_arc) [label release]; #endif
它显示如下:
请记住,如果 leftBarButtonItem 不是 nil ,则 titleView 属性为ignored .
leftBarButtonItem
nil
对于Swift:
let label = UILabel(frame: CGRectMake(0, 0, UIScreen.main.bounds.width, 44)) label.backgroundColor = UIColor.clearColor() label.numberOfLines = 0 label.textAlignment = NSTextAlignment.Center label.text = "multiline string" self.navigationItem.titleView = label
对于swift 4:
let label = UILabel(frame: CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.width, height: 44.0)) label.backgroundColor = UIColor.clear label.numberOfLines = 0 label.textAlignment = NSTextAlignment.center label.text = "first line\nsecond line" self.navigationItem.titleView = label
Swift解决方案:
NavigationBar 中的2行:
NavigationBar
private func setupTitleView() { let topText = NSLocalizedString("key", comment: "") let bottomText = NSLocalizedString("key", comment: "") let titleParameters = [NSForegroundColorAttributeName : UIColor.<Color>(), NSFontAttributeName : UIFont.<Font>] let subtitleParameters = [NSForegroundColorAttributeName : UIColor.<Color>(), NSFontAttributeName : UIFont.<Font>] let title:NSMutableAttributedString = NSMutableAttributedString(string: topText, attributes: titleParameters) let subtitle:NSAttributedString = NSAttributedString(string: bottomText, attributes: subtitleParameters) title.appendAttributedString(NSAttributedString(string: "\n")) title.appendAttributedString(subtitle) let size = title.size() let width = size.width guard let height = navigationController?.navigationBar.frame.size.height else {return} let titleLabel = UILabel(frame: CGRectMake(0,0, width, height)) titleLabel.attributedText = title titleLabel.numberOfLines = 0 titleLabel.textAlignment = .Center navigationItem.titleView = titleLabel }
BarButton 中的2行
BarButton
let string = NSLocalizedString("key", comment: "") let attributes = [NSForegroundColorAttributeName : UIColor.<Color>, NSFontAttributeName : UIFont.<Font>] let size = (string as NSString).sizeWithAttributes(attributes) guard let height = navigationController?.navigationBar.frame.size.height else {return} let button:UIButton = UIButton(frame: CGRectMake(0, 0, size.width, height)) button.setAttributedTitle(NSAttributedString(string: string, attributes: attributes), forState: .Normal) button.addTarget(self, action: #selector(<SELECTOR>), forControlEvents: .TouchUpInside) button.titleLabel?.numberOfLines = 0 button.titleLabel?.textAlignment = .Right let rightBarButton = UIBarButtonItem(customView: button) navigationItem.rightBarButtonItem = rightBarButton
结果 -
经过大量的调整后,我仍然无法在iOS 8中为我工作 . 这是适用于iOS 8/9的可复制粘贴的解决方案 . 积分转到Matt Curtis's github post
- (void) viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; if(!self.navigationItem.titleView){ self.navigationItem.titleView = ({ UILabel *titleView = [UILabel new]; titleView.numberOfLines = 0; titleView.textAlignment = NSTextAlignmentCenter; titleView.attributedText = [[NSAttributedString alloc] initWithString:@"2\nLINES" attributes: self.navigationController.navigationBar.titleTextAttributes ]; [titleView sizeToFit]; // You'll need to set your frame otherwise if your line breaks aren't explcit. titleView; }); } }
What to do when label is not centered
如果您遇到与我相同的问题 - 由于后退按钮,该标签不在navigationItem中居中,请将您的UILabel嵌入到UIView中 . 然后UILabel不会被迫增长's text, but stop growing when it'宽度提升视图的宽度 . 有关此问题的更多信息,请访问:Can't set titleView in the center of navigation bar because back button(Darren的回答)
不居中:
- (void)setTwoLineTitle:(NSString *)titleText color:(UIColor *)color font:(UIFont *)font { CGFloat titleLabelWidth = [UIScreen mainScreen].bounds.size.width/2; UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, titleLabelWidth, 44)]; label.backgroundColor = [UIColor clearColor]; label.numberOfLines = 2; label.font = font; label.adjustsFontSizeToFitWidth = YES; label.textAlignment = UITextAlignmentCenter; label.textColor = color; label.text = titleText; self.navigationItem.titleView = label; }
居中:
- (void)setTwoLineTitle:(NSString *)titleText color:(UIColor *)color font:(UIFont *)font { CGFloat titleLabelWidth = [UIScreen mainScreen].bounds.size.width/2; UIView *wrapperView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, titleLabelWidth, 44)]; UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, titleLabelWidth, 44)]; label.backgroundColor = [UIColor clearColor]; label.numberOfLines = 2; label.font = font; label.adjustsFontSizeToFitWidth = YES; label.textAlignment = UITextAlignmentCenter; label.textColor = color; label.text = titleText; [wrapperView addSubview:label]; self.navigationItem.titleView = wrapperView; }
这是处理多行 Headers 的 Swift 3 版本:
override func viewDidLoad() { super.viewDidLoad() let label = UILabel(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 44)) label.backgroundColor = .clear label.numberOfLines = 0 label.textAlignment = .center label.font = UIFont.boldSystemFont(ofSize: 14.0) label.text = "This is a Multi-Line title of UINavigationBar" self.navigationItem.titleView = label }
这是一种 Swift 4 方式 -
let upperTitle = NSMutableAttributedString(string: "\(text1)", attributes: [NSAttributedStringKey.font: UIFont(name: "SFProDisplay-Heavy", size: 17)!]) let lowerTitle = NSMutableAttributedString(string: "\n\((text2)!)", attributes: [NSAttributedStringKey.font: UIFont(name: "SFProText-Light", size: 11)! , NSAttributedStringKey.foregroundColor: UIColor(hex: "#607D8B")]) upperTitle.append(lowerTitle) let label1 = UILabel(frame: CGRect(x: 0, y: 0, width: 400, height:44)) label1.numberOfLines = 0 label1.textAlignment = .center label1.attributedText = upperTitle //assign it to attributedText instead of text self.navigationItem.titleView = label1
除了来自@gbk的解决方案之外,大多数解决方案都使用硬编码高度44pt作为UIView(包装器视图)和UILabel . 全部都是由代码创建的 . 我忽略了动态读取导航栏高度的@gbk解决方案 .
在iOS 11(iPhone 5s)上 orientation = landscape 时遇到了问题 . 标签's height won' t进行调整,当我为横向设置一行文本时,文本对齐到导航栏的底部 .
orientation = landscape
不知怎的,我发现我可以在故事板中添加UILabel并为此创建一个IBOutlet . 那不是更好吗?
在故事板中添加UIView到导航栏 . 将其拖动到导航栏上时,它将显示为蓝色框 . 如果出现垂直笔划,则将其添加到左/右栏按钮项目数组中 . 注意:只能有一个UIView . 如果正确添加,它将显示在场景面板(左侧)的 Navigation Item 下 .
Navigation Item
将UILabel拖入此UIView .
由于UIView没有SIZE但集中在导航栏中,因此无法添加四个零的约束 . 只需向UILabel添加两个约束,使其位于superview的中心:将中心X和Y对齐到Superview .
像往常一样配置UILabel . 对于多行,我将行数设置为零(0) .
在视图控制器上创建 IBOutlet ,您可以照常使用它 . 要使用不同大小的文本,请使用属性字符串(上面有很多解决方案) .
IBOutlet
我在带有iOS 11.2.6的iPhone 5s上进行了测试,文本位于中心位置没有任何问题,在纵向和横向上工作正常 .
Swift 4
extension UINavigationItem { @objc func setTwoLineTitle(lineOne: String, lineTwo: String) { let titleParameters = [NSAttributedStringKey.foregroundColor : UIColor.white, NSAttributedStringKey.font : UIFont.boldSystemFont(ofSize: 17)] as [NSAttributedStringKey : Any] let subtitleParameters = [NSAttributedStringKey.foregroundColor : UIColor.flatWhite(), NSAttributedStringKey.font : UIFont.systemFont(ofSize: 12)] as [NSAttributedStringKey : Any] let title:NSMutableAttributedString = NSMutableAttributedString(string: lineOne, attributes: titleParameters) let subtitle:NSAttributedString = NSAttributedString(string: lineTwo, attributes: subtitleParameters) title.append(NSAttributedString(string: "\n")) title.append(subtitle) let size = title.size() let width = size.width let height = CGFloat(44) let titleLabel = UILabel(frame: CGRect.init(x: 0, y: 0, width: width, height: height)) titleLabel.attributedText = title titleLabel.numberOfLines = 0 titleLabel.textAlignment = .center titleView = titleLabel } }
Font, color, and navigation bar height are hardcoded here.
9 回答
设置
UINavigationItem
的titleView
属性 . 例如,在视图控制器的viewDidLoad
方法中,您可以执行以下操作:它显示如下:
请记住,如果
leftBarButtonItem
不是nil
,则titleView
属性为ignored .对于Swift:
对于swift 4:
Swift解决方案:
NavigationBar
中的2行:BarButton
中的2行结果 -
经过大量的调整后,我仍然无法在iOS 8中为我工作 . 这是适用于iOS 8/9的可复制粘贴的解决方案 . 积分转到Matt Curtis's github post
What to do when label is not centered
如果您遇到与我相同的问题 - 由于后退按钮,该标签不在navigationItem中居中,请将您的UILabel嵌入到UIView中 . 然后UILabel不会被迫增长's text, but stop growing when it'宽度提升视图的宽度 . 有关此问题的更多信息,请访问:Can't set titleView in the center of navigation bar because back button(Darren的回答)
不居中:
居中:
这是处理多行 Headers 的 Swift 3 版本:
这是一种 Swift 4 方式 -
除了来自@gbk的解决方案之外,大多数解决方案都使用硬编码高度44pt作为UIView(包装器视图)和UILabel . 全部都是由代码创建的 . 我忽略了动态读取导航栏高度的@gbk解决方案 .
在iOS 11(iPhone 5s)上
orientation = landscape
时遇到了问题 . 标签's height won' t进行调整,当我为横向设置一行文本时,文本对齐到导航栏的底部 .不知怎的,我发现我可以在故事板中添加UILabel并为此创建一个IBOutlet . 那不是更好吗?
在故事板中添加UIView到导航栏 . 将其拖动到导航栏上时,它将显示为蓝色框 . 如果出现垂直笔划,则将其添加到左/右栏按钮项目数组中 . 注意:只能有一个UIView . 如果正确添加,它将显示在场景面板(左侧)的
Navigation Item
下 .将UILabel拖入此UIView .
由于UIView没有SIZE但集中在导航栏中,因此无法添加四个零的约束 . 只需向UILabel添加两个约束,使其位于superview的中心:将中心X和Y对齐到Superview .
像往常一样配置UILabel . 对于多行,我将行数设置为零(0) .
在视图控制器上创建
IBOutlet
,您可以照常使用它 . 要使用不同大小的文本,请使用属性字符串(上面有很多解决方案) .我在带有iOS 11.2.6的iPhone 5s上进行了测试,文本位于中心位置没有任何问题,在纵向和横向上工作正常 .
Swift 4
Font, color, and navigation bar height are hardcoded here.