我使用的是 Rodrigo Pedroso's answer,但它不会截断长标题这一事实成为一个问题。我制作了一个版本,用于测量栏按钮项之间的标题有多少空间,然后手动截断标题以适应该空间。截断代码改编自这个答案,有点乱——也许有人可以帮助找出一种使用 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
}
}
}