Swift:如何计算居中字符串的大小

时间:2017-09-27 16:35:31

标签: ios swift string

我目前正在计算字符串的大小,如下所示。如何对居中的字符串进行此计算?

func sizeOfString (string: String, constrainedToWidth width: Double, font: UIFont) -> CGSize {
    return (string as NSString).boundingRect(with: CGSize(width: width, height: Double.greatestFiniteMagnitude),
                                             options: NSStringDrawingOptions.usesLineFragmentOrigin,
                                             attributes: [NSFontAttributeName: font],
                                             context: nil).size
}

2 个答案:

答案 0 :(得分:0)

Objective-C 版本

UIFont *font = [UIFont fontWithName:@"Helvetica" size:30];
NSDictionary *userAttributes = @{NSFontAttributeName: font,
                                 NSForegroundColorAttributeName: [UIColor blackColor]};
NSString *text = @"hello";
...
const CGSize textSize = [text sizeWithAttributes: userAttributes];

Swift 版本:

extension String {
    func size(OfFont font: UIFont) -> CGSize {
        return (self as NSString).size(attributes: [NSFontAttributeName: font])
    }
}

用法:

let string = "hello world!"
let font = UIFont.systemFont(ofSize: 12)
let width = string.size(OfFont: font).width // size: {w: 98.912 h: 14.32}

答案 1 :(得分:0)

你说:

  

其他一些必须影响结果,因为字符串在计算之前会转到2行大约两个字符。

是的,如果你自己渲染字符串,boundingRect将捕获字符串的大小(例如draw(in:withAttributes:)。但UILabel可以想象做各种其他事情(插入从边缘等)。

我觉得你有两个基本选择:

  1. 如今,您已获取集合视图流布局的布局,并将其itemSize设置为UICollectionViewFlowLayoutAutomaticSize(在iOS 10及更高版本中):

    let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
    layout.itemSize = UICollectionViewFlowLayoutAutomaticSize
    layout.estimatedItemSize = ...
    

    然后将根据单元格中的自动布局约束自动调整单元格的大小(例如,标签的固定宽度,允许固有尺寸控制高度,可能大小<=某个最大尺寸)。

  2. 如果您想自己计算boundingRect,那么您也可以使用draw(in:withAttributes:)自行渲染,避免UILabel的任何特殊行为在幕后做:

    let string = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam quis leo convallis, euismod ipsum sed, lacinia diam. Nam sit amet justo id lacus blandit sodales id et."
    
    let paragraphStyle = NSMutableParagraphStyle()
    paragraphStyle.lineBreakMode = .byWordWrapping
    paragraphStyle.alignment = .center
    
    let attributes: [NSAttributedStringKey: Any] = [
        .font: font,
        .paragraphStyle: paragraphStyle
    ]
    
    let rect = string.boundingRect(with: CGSize(width: width, height: .greatestFiniteMagnitude),
                                   options: .usesLineFragmentOrigin,
                                   attributes: attributes,
                                   context: nil)
    
    UIGraphicsBeginImageContextWithOptions(rect.size, false, 0)
    string.draw(in: rect, withAttributes: attributes)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    

    然后,您可以使用imagerect获取UIImageView