在iOS 上计算字符串排版时占用的size大小
矩形排版
矩形排版使用函数boundingRectWithSize
1 | @interface NSString (NSExtendedStringDrawing) |
size参数设置要期望限制的尺寸,一般是指定排版时的宽度,指定一个足够大的高度。最后的结果就是实际排版时需要的高度。如果指定的高度比实际需要的小,就会返回比限制尺寸小的尺寸,最后文本会被截断。
options描述排版参数,需要指定为NSStringDrawingUsesLineFragmentOrigin或0,否则计算排版尺寸时按不换行计算。
attributes字段指示排版时的文字属性。NSAttributedString自身包含了属性信息,所以计算时不需要额外提供该参数。
最长用的key为NSFontAttributeName,用来指定排版时使用的字体。
下面为所有有效的key指,摘自NSAttributedString.h文件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21UIKIT_EXTERN NSString *const NSFontAttributeName NS_AVAILABLE_IOS(6_0); // UIFont, default Helvetica(Neue) 12
UIKIT_EXTERN NSString *const NSParagraphStyleAttributeName NS_AVAILABLE_IOS(6_0); // NSParagraphStyle, default defaultParagraphStyle
UIKIT_EXTERN NSString *const NSForegroundColorAttributeName NS_AVAILABLE_IOS(6_0); // UIColor, default blackColor
UIKIT_EXTERN NSString *const NSBackgroundColorAttributeName NS_AVAILABLE_IOS(6_0); // UIColor, default nil: no background
UIKIT_EXTERN NSString *const NSLigatureAttributeName NS_AVAILABLE_IOS(6_0); // NSNumber containing integer, default 1: default ligatures, 0: no ligatures
UIKIT_EXTERN NSString *const NSKernAttributeName NS_AVAILABLE_IOS(6_0); // NSNumber containing floating point value, in points; amount to modify default kerning. 0 means kerning is disabled.
UIKIT_EXTERN NSString *const NSStrikethroughStyleAttributeName NS_AVAILABLE_IOS(6_0); // NSNumber containing integer, default 0: no strikethrough
UIKIT_EXTERN NSString *const NSUnderlineStyleAttributeName NS_AVAILABLE_IOS(6_0); // NSNumber containing integer, default 0: no underline
UIKIT_EXTERN NSString *const NSStrokeColorAttributeName NS_AVAILABLE_IOS(6_0); // UIColor, default nil: same as foreground color
UIKIT_EXTERN NSString *const NSStrokeWidthAttributeName NS_AVAILABLE_IOS(6_0); // NSNumber containing floating point value, in percent of font point size, default 0: no stroke; positive for stroke alone, negative for stroke and fill (a typical value for outlined text would be 3.0)
UIKIT_EXTERN NSString *const NSShadowAttributeName NS_AVAILABLE_IOS(6_0); // NSShadow, default nil: no shadow
UIKIT_EXTERN NSString *const NSTextEffectAttributeName NS_AVAILABLE_IOS(7_0); // NSString, default nil: no text effect
UIKIT_EXTERN NSString *const NSAttachmentAttributeName NS_AVAILABLE_IOS(7_0); // NSTextAttachment, default nil
UIKIT_EXTERN NSString *const NSLinkAttributeName NS_AVAILABLE_IOS(7_0); // NSURL (preferred) or NSString
UIKIT_EXTERN NSString *const NSBaselineOffsetAttributeName NS_AVAILABLE_IOS(7_0); // NSNumber containing floating point value, in points; offset from baseline, default 0
UIKIT_EXTERN NSString *const NSUnderlineColorAttributeName NS_AVAILABLE_IOS(7_0); // UIColor, default nil: same as foreground color
UIKIT_EXTERN NSString *const NSStrikethroughColorAttributeName NS_AVAILABLE_IOS(7_0); // UIColor, default nil: same as foreground color
UIKIT_EXTERN NSString *const NSObliquenessAttributeName NS_AVAILABLE_IOS(7_0); // NSNumber containing floating point value; skew to be applied to glyphs, default 0: no skew
UIKIT_EXTERN NSString *const NSExpansionAttributeName NS_AVAILABLE_IOS(7_0); // NSNumber containing floating point value; log of expansion factor to be applied to glyphs, default 0: no expansion
UIKIT_EXTERN NSString *const NSWritingDirectionAttributeName NS_AVAILABLE_IOS(7_0); // NSArray of NSNumbers representing the nested levels of writing direction overrides as defined by Unicode LRE, RLE, LRO, and RLO characters. The control characters can be obtained by masking NSWritingDirection and NSTextWritingDirection values. LRE: NSWritingDirectionLeftToRight|NSTextWritingDirectionEmbedding, RLE: NSWritingDirectionRightToLeft|NSTextWritingDirectionEmbedding, LRO: NSWritingDirectionLeftToRight|NSTextWritingDirectionOverride, RLO: NSWritingDirectionRightToLeft|NSTextWritingDirectionOverride,
UIKIT_EXTERN NSString *const NSVerticalGlyphFormAttributeName NS_AVAILABLE_IOS(6_0);context参数为排版字段上下文,可以为nil
不规则形状排版
上面用到的是矩形排版尺寸的计算,有时候排版的尺寸不是矩形,如图文混排时。
这时候我们需要借助text kit框架的帮助。
这里以一片排版区域左上角和右上角各有一张小图片,文字需要按“由”字形排版。
1 | NSString *str = ...; |
这里我们借助NSLayoutManager的boundingRectForGlyphRange:NSMakeRange函数来计算排版结果需要的尺寸。
1 |
因为UILabel不能访问内部的textkit属性,所以需要使用UITextView来展示文字。因为UITextView在显示内容时留了页边。所以在根据计算的结果设置UITextView的frame时需要加上页边距。