带有副标题的UINavigationBar TitleView

我想在我的UINavigationBar中有一个titleView,它有两行文本,而不是只有一行

当我有一个“返回”button和一个“编辑”button,因为它看起来接近居中,我目前的实施工作得很好。 问题是当我只有一个button。 它看起来很奇怪和错误,因为视图集中在可用空间上。

带有左右button的UINavigationBar

UINavigationBar只有一个button

这是我目前的实现:

CGRect frame = self.navigationController.navigationBar.frame; UIView *twoLineTitleView = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetWidth(frame), 0, CGRectGetWidth(frame), CGRectGetHeight(frame))]; UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 8, CGRectGetWidth(frame), 14)]; titleLabel.backgroundColor = [UIColor clearColor]; titleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth; titleLabel.textAlignment = UITextAlignmentCenter; titleLabel.text = self.title; [twoLineTitleView addSubview:titleLabel]; UILabel *subTitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 23, CGRectGetWidth(frame), 14)]; subTitleLabel.backgroundColor = [UIColor clearColor]; subTitleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth; subTitleLabel.textAlignment = UITextAlignmentCenter; subTitleLabel.text = self.subTitle; [twoLineTitleView addSubview:subTitleLabel]; self.navigationItem.titleView = twoLineTitleView; 

这是我将如何做到这一点: – 使用sizeToFit为你的两个标签。 – 将容器视图的宽度设置为两个标签的最大宽度 – 将两个标签中较小的一个居中放置在视图上

这个代码应该适合你:

  UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 0, 0)]; titleLabel.backgroundColor = [UIColor clearColor]; titleLabel.textColor = [UIColor whiteColor]; titleLabel.font = [UIFont boldSystemFontOfSize:20]; titleLabel.text = @"Your Title"; [titleLabel sizeToFit]; UILabel *subTitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 22, 0, 0)]; subTitleLabel.backgroundColor = [UIColor clearColor]; subTitleLabel.textColor = [UIColor whiteColor]; subTitleLabel.font = [UIFont systemFontOfSize:12]; subTitleLabel.text = @"Your subtitle"; [subTitleLabel sizeToFit]; UIView *twoLineTitleView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, MAX(subTitleLabel.frame.size.width, titleLabel.frame.size.width), 30)]; [twoLineTitleView addSubview:titleLabel]; [twoLineTitleView addSubview:subTitleLabel]; float widthDiff = subTitleLabel.frame.size.width - titleLabel.frame.size.width; if (widthDiff > 0) { CGRect frame = titleLabel.frame; frame.origin.x = widthDiff / 2; titleLabel.frame = CGRectIntegral(frame); }else{ CGRect frame = subTitleLabel.frame; frame.origin.x = abs(widthDiff) / 2; subTitleLabel.frame = CGRectIntegral(frame); } self.navigationItem.titleView = twoLineTitleView; 

Swift 3 varient:

  let titleLabel = UILabel.init(frame: CGRect.zero) titleLabel.backgroundColor = UIColor.clear titleLabel.textColor = UIColor.schBlack titleLabel.font = UIFont.schTextStyle2Font() titleLabel.text = titleString; titleLabel.sizeToFit() let subTitleLabel = UILabel.init(frame: CGRect.init(x: 0, y: 22, width: 0, height: 0)) subTitleLabel.backgroundColor = UIColor.clear subTitleLabel.textColor = UIColor.schBrownishGrey subTitleLabel.font = UIFont.schTextStyle3Font() subTitleLabel.text = subTitleString; subTitleLabel.sizeToFit() let twoLineTitleView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: self.view.frame.width-40, height: 30)) twoLineTitleView.addSubview(titleLabel) twoLineTitleView.addSubview(subTitleLabel) /* float widthDiff = subTitleLabel.frame.size.width - titleLabel.frame.size.width; if (widthDiff > 0) { CGRect frame = titleLabel.frame; frame.origin.x = widthDiff / 2; titleLabel.frame = CGRectIntegral(frame); }else{ CGRect frame = subTitleLabel.frame; frame.origin.x = abs(widthDiff) / 2; subTitleLabel.frame = CGRectIntegral(frame); } */ self.navigationItem.titleView = twoLineTitleView; 

另一种方法可能是使用提示 。

Brian van den hovel为了更好地集中标题和副标题而增加了一些内容。

 func setTitle(title:String, subtitle:String) -> UIView { //Create a label programmatically and give it its property's let titleLabel = UILabel(frame: CGRectMake(0, 0, 0, 0)) //x, y, width, height where y is to offset from the view center titleLabel.backgroundColor = UIColor.clearColor() titleLabel.textColor = UIColor.blackColor() titleLabel.font = UIFont.boldSystemFontOfSize(17) titleLabel.text = title titleLabel.sizeToFit() //Create a label for the Subtitle let subtitleLabel = UILabel(frame: CGRectMake(0, 18, 0, 0)) subtitleLabel.backgroundColor = UIColor.clearColor() subtitleLabel.textColor = UIColor.lightGrayColor() subtitleLabel.font = UIFont.systemFontOfSize(12) subtitleLabel.text = subtitle subtitleLabel.sizeToFit() // Create a view and add titleLabel and subtitleLabel as subviews setting let titleView = UIView(frame: CGRectMake(0, 0, max(titleLabel.frame.size.width, subtitleLabel.frame.size.width), 30)) // Center title or subtitle on screen (depending on which is larger) if titleLabel.frame.width >= subtitleLabel.frame.width { var adjustment = subtitleLabel.frame adjustment.origin.x = titleView.frame.origin.x + (titleView.frame.width/2) - (subtitleLabel.frame.width/2) subtitleLabel.frame = adjustment } else { var adjustment = titleLabel.frame adjustment.origin.x = titleView.frame.origin.x + (titleView.frame.width/2) - (titleLabel.frame.width/2) titleLabel.frame = adjustment } titleView.addSubview(titleLabel) titleView.addSubview(subtitleLabel) return titleView } 

您也可以使用属性string来实现相同的结果:

 let subtitleAttribute = [NSForegroundColorAttributeName: UIColor.grayColor() , NSFontAttributeName: UIFont.systemFontOfSize(12.0)] let titleString = NSMutableAttributedString(string: "title" + "\n", attributes: [NSFontAttributeName: UIFont.boldSystemFontOfSize(17.0)]) let subtitleString = NSAttributedString(string: "subtitle", attributes: subtitleAttribute) titleString.appendAttributedString(subtitleString) let label = UILabel(frame: CGRectMake(0, 0, titleString.size().width, 44)) label.numberOfLines = 0 label.textAlignment = NSTextAlignment.Center label.attributedText = titleString self.navigationItem.titleView = label 

Swift 3

 let subtitleAttribute = [NSForegroundColorAttributeName: UIColor.gray , NSFontAttributeName: UIFont.systemFont(ofSize: 12.0)] let titleString = NSMutableAttributedString(string: "title" + "\n", attributes: [NSFontAttributeName: UIFont.boldSystemFont(ofSize: 17.0)]) let subtitleString = NSAttributedString(string: "subtitle", attributes: subtitleAttribute) titleString.append(subtitleString) let label = UILabel(frame: CGRect(x: 0, y: 0, width: titleString.size().width, height: 44)) label.numberOfLines = 0 label.textAlignment = NSTextAlignment.center label.attributedText = titleString self.navigationItem.titleView = label 

除了github ! 这里。

我发现,当我的字幕小于我的标题,它不会正确格式化,这里是正确的代码。

 //Usage: self.navigationItem.titleView = setTitle(varDec.currentDate(), subtitle: varDec.currentDay()) func setTitle(title:String, subtitle:String) -> UIView { //Create a label programmatically and give it its property's let titleLabel = UILabel(frame: CGRectMake(0, -5, 0, 0)) //x, y, width, height where y is to offset from the view center titleLabel.backgroundColor = UIColor.clearColor() titleLabel.textColor = UIColor.blackColor() titleLabel.font = UIFont.boldSystemFontOfSize(17) titleLabel.text = title titleLabel.sizeToFit() //Create a label for the Subtitle // x, y, width, height where x is set to be half the size of the title (100/4 = 25%) as it starts all the way left. let subtitleLabel = UILabel(frame: CGRectMake(titleLabel.frame.size.width / 4, 18, 0, 0)) subtitleLabel.backgroundColor = UIColor.clearColor() subtitleLabel.textColor = UIColor.lightGrayColor() subtitleLabel.font = UIFont.systemFontOfSize(12) subtitleLabel.text = subtitle subtitleLabel.sizeToFit() /*Create a view and add titleLabel and subtitleLabel as subviews setting * its width to the bigger of both * this will crash the program if subtitle is bigger then title */ let titleView = UIView(frame: CGRectMake(0, 0, max(titleLabel.frame.size.width, subtitleLabel.frame.size.width), 30)) titleView.addSubview(titleLabel) titleView.addSubview(subtitleLabel) return titleView } 

https://www.reddit.com/r/swift/comments/3izq7b/style_guidelines_for_navigation_bar_prompts/

 extension UINavigationItem { //Make the title 2 lines with a title and a subtitle func addTitleAndSubtitleToNavigationBar (title: String, subtitle: String) { var label = UILabel(frame: CGRectMake(10.0, 0.0, 50.0, 40.0)) label.font = UIFont.boldSystemFontOfSize(14.0) label.numberOfLines = 2 label.text = "\(title)\n\(subtitle)" label.textColor = UIColor.blackColor() label.sizeToFit() label.textAlignment = NSTextAlignment.Center self.titleView = label } } 

我完全replace了标题视图。 最终结果如下所示:

在这里输入图像说明

它可以通过viewDidLoad方法中的以下代码来实现。

 UIView * containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 220, 40)]; UILabel * titleLabel = [[UILabel alloc] init]; titleLabel.text = @"Ttitle"; titleLabel.textAlignment = NSTextAlignmentCenter; titleLabel.font = [UIFont boldSystemFontOfSize:titleLabel.font.pointSize]; [containerView addSubview:titleLabel]; titleLabel.keepInsets.equal = 0; titleLabel.keepBottomInset.equal = 10; UILabel * subtitleLabel = [[UILabel alloc] init]; subtitleLabel.textAlignment = NSTextAlignmentCenter; subtitleLabel.font = [UIFont italicSystemFontOfSize:12.0]; subtitleLabel.textColor = [UIColor lightGrayColor]; [containerView addSubview:subtitleLabel]; subtitleLabel.keepHeight.equal = 15; subtitleLabel.keepWidth.equal = 200; subtitleLabel.keepBottomInset.equal = 0; subtitleLabel.keepHorizontalCenter.equal = 0.5; subtitleLabel.text = @"Subtitle"; [self.navigationItem setTitleView:containerView]; 

为此,我使用了优秀的KeepLayout库。 它产生这样的结果:

我正在使用罗德里戈·佩德罗索的回答 ,但事实上,它不截断长标题成为一个问题。 我做了一个版本,测量条形button项目之间的标题有多less空间,然后手动截断标题以适应该空间。 截断代码是从这个答案改编的,有点乱,也许有人可以帮助找出一种方法来使用UILabel的内置截断方法(即.ByTruncatingTail)。 我已经花了太多的时间在这个。

这是我得到的:

 extension UIViewController { private var availableWidthForTitle: CGFloat { get { var total = UIScreen.mainScreen().bounds.width if let navigationBar = navigationController?.navigationBar { var maxYLeft: CGFloat = 0 var minYRight: CGFloat = 0 for subview in navigationBar.subviews.dropFirst() where !subview.hidden { if subview.frame.origin.x < total / 2 { let rightEdge = subview.frame.origin.x + subview.frame.size.width if rightEdge < total / 2 { maxYLeft = max(maxYLeft, rightEdge) } } else { let leftEdge = subview.frame.origin.x if leftEdge > total / 2 { minYRight = min(minYRight, total - leftEdge) } } } total = total - maxYLeft - minYRight } return total } } func setTitle(title:String, subtitle:String?) { if (subtitle == nil) { self.title = title.uppercaseString } else { let titleLabel = UILabel(frame: CGRectMake(0, -2, 0, 0)) titleLabel.backgroundColor = UIColor.clearColor() titleLabel.textColor = MaterialColor.white titleLabel.font = RobotoFont.boldWithSize(17) titleLabel.textAlignment = .Center let availableWidth = availableWidthForTitle let titleUppercase = NSString(string: title.uppercaseString) if titleUppercase.boundingRectWithSize( // if title needs to be truncated CGSize(width: CGFloat.max, height: CGFloat.max), options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName : titleLabel.font], context: nil).width > availableWidth { let truncTitle: NSMutableString = "" for nextChar in title.uppercaseString.characters { if truncTitle.boundingRectWithSize( CGSize(width: CGFloat.max, height: CGFloat.max), options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName : titleLabel.font], context: nil).width > availableWidth - 16 { // for ellipsis + some margin truncTitle.appendString("...") break } else { truncTitle.appendString(String(nextChar)) } } titleLabel.text = truncTitle as String } else { // use title as-is titleLabel.text = titleUppercase as String } titleLabel.sizeToFit() let subtitleLabel = UILabel(frame: CGRectMake(0, 18, 0, 0)) subtitleLabel.backgroundColor = UIColor.clearColor() subtitleLabel.textColor = MaterialColor.white subtitleLabel.font = MaterialFont.italicSystemFontWithSize(10) subtitleLabel.text = subtitle subtitleLabel.sizeToFit() let titleView = UIView(frame: CGRectMake(0, 0, max(titleLabel.frame.size.width, subtitleLabel.frame.size.width), 30)) // Center title or subtitle on screen (depending on which is larger) if titleLabel.frame.width >= subtitleLabel.frame.width { var adjustment = subtitleLabel.frame adjustment.origin.x = titleView.frame.origin.x + (titleView.frame.width/2) - (subtitleLabel.frame.width/2) subtitleLabel.frame = adjustment } else { var adjustment = titleLabel.frame adjustment.origin.x = titleView.frame.origin.x + (titleView.frame.width/2) - (titleLabel.frame.width/2) titleLabel.frame = adjustment } titleView.addSubview(titleLabel) titleView.addSubview(subtitleLabel) self.navigationItem.titleView = titleView } } } 

受@Ben Smiley启发,我添加了一个砌体实现。

 CGFloat width = 200; CGFloat titleHeight = 25; CGFloat containerHeight = 40; UIView * containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, containerHeight)]; UILabel * titleLabel = [[UILabel alloc] init]; titleLabel.text = @"Title"; titleLabel.textAlignment = NSTextAlignmentCenter; titleLabel.font = [UIFont boldSystemFontOfSize:titleLabel.font.pointSize]; [containerView addSubview:titleLabel]; [titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.top.mas_equalTo(0); make.left.mas_equalTo(0); make.right.mas_equalTo(0); make.width.mas_equalTo(width); make.height.mas_equalTo(titleHeight); }]; UILabel * subtitleLabel = [[UILabel alloc] init]; subtitleLabel.textAlignment = NSTextAlignmentCenter; subtitleLabel.font = [UIFont systemFontOfSize:12]; [containerView addSubview:subtitleLabel]; [subtitleLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.left.mas_equalTo(0); make.right.mas_equalTo(0); make.top.mas_equalTo(titleLabel.mas_bottom); make.width.mas_equalTo(width); make.height.mas_equalTo(containerHeight - titleHeight); }]; subtitleLabel.text = @"Subtitle"; [self.navigationItem setTitleView:containerView];