使用 Core Text 的多语言布局中的行间距
属性字符串只有一个属性 - 17 点 Helvetica NeueUI 字体 - 覆盖整个字符串。第1~3行是纯英文,第4~6行是英文和中文混合,第7~8行是纯中文。
然后使用 CTFramesetter 对其进行布局,并使用 CTFrameDraw 绘制生成的框架。
// UIView subclass
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor whiteColor];
CTFontRef font = CTFontCreateWithName(CFSTR("Helvetica NeueUI"), 17.f, NULL);
_text = [[NSAttributedString alloc] initWithString:string attributes:
[NSDictionary dictionaryWithObject:(id)font forKey:(id)kCTFontAttributeName]];
CFRelease(font);
_framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)_text);
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, self.bounds);
_frame = CTFramesetterCreateFrame(_framesetter, CFRangeMake(0, 0), path, NULL);
CGPathRelease(path);
}
return self;
}
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
// Flip the coordinate system.
CGContextTranslateCTM(context, 0.f, self.bounds.size.height);
CGContextScaleCTM(context, 1.f, -1.f);
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CTFrameDraw(_frame, context);
CGContextRestoreGState(context);
}
问题是7号线和8号线(纯中文线路)之间的间距比其他线要小得多。
作为对比,我在其下方放置了一个 UILabel
,具有相同的字体和文本。忽略单个字符的渲染差异,可以看到 UILabel
中的行间距是统一的,包括两行中文之间的最后一行。
(来源:skitch.com)
通知< /strong>:上面的结果是在真实设备上获得的。如果您在模拟器上运行相同的代码,您将在核心文本视图中得到非常不同的结果 - 包含中文的行之间的空格比其他行大得多。
- 为什么中文行间距较小(较大)?
- 如何使用 Core Text 布局具有统一行高的多语言文本?
PS:这是示例项目,您可以自己尝试。
The attributed string has only one attribute - 17 point Helvetica NeueUI font - covering the whole string. Line 1~3 are purely English, line 4~6 are mixtures of English and Chinese, line 7~8 are purely Chinese.
It is then layouted with CTFramesetter and resultant frame is drawn with CTFrameDraw.
// UIView subclass
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor whiteColor];
CTFontRef font = CTFontCreateWithName(CFSTR("Helvetica NeueUI"), 17.f, NULL);
_text = [[NSAttributedString alloc] initWithString:string attributes:
[NSDictionary dictionaryWithObject:(id)font forKey:(id)kCTFontAttributeName]];
CFRelease(font);
_framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)_text);
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, self.bounds);
_frame = CTFramesetterCreateFrame(_framesetter, CFRangeMake(0, 0), path, NULL);
CGPathRelease(path);
}
return self;
}
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
// Flip the coordinate system.
CGContextTranslateCTM(context, 0.f, self.bounds.size.height);
CGContextScaleCTM(context, 1.f, -1.f);
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CTFrameDraw(_frame, context);
CGContextRestoreGState(context);
}
The problem is that the space between line 7 and 8 (purely Chinese lines) is much smaller than others.
For contrast, I put a UILabel
below it, with the same font and text. Ignoring the rendering difference of single characters, you can see the line spaces in UILabel
are uniform including the last one between two Chinese lines.
(source: skitch.com)
Notice: this results above is got on a real device. If you run the same code on the simulator, you'll get very different result for the Core Text view — spaces between lines containing Chinese are much larger than others.
- Why is the space between Chinese lines smaller(larger)?
- How can I layout multi-language text with uniform line height using Core Text?
PS: here is the sample project you can try yourself.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
与欧洲语言中每个字母之间的间距类似,中文书写在字符之间使用狭窄的间距,尽管除了极少数情况外,它并没有观察到与单词之间较宽的间距相同的情况。 (在这方面,它可能有点类似于 scriptio Continua 的一种形式。)
当使用空格时,它也是全角的。其用法的一个例子是作为敬意标记。台湾的一个现代例子是,将蒋介石称为先总统蒋公(前总统蒋公),其中前面的空格是对蒋公的尊称标记。这种用法在非常正式的信件或其他旧式文档中仍然存在。
当中文以音译形式书写时(如汉语拼音),空格用于辅助阅读。来源:http://en.wikipedia.org/wiki/Chinese_punctuation
所以这是因为中文中空格的使用与英语中有点不同。
Similarly to the space between each letter in European languages, Chinese writing uses a narrow space between characters, though it does not observe the equivalent to the wider space between words, except in rare occasions. (In this respect, it may somewhat resemble a form of scriptio continua.)
When space is used, it is also fullwidth. One instance of its usage is as an honorific marker. A modern example in Taiwan, is found in the reference to Chiang Kai-shek as 先總統 蔣公 (Former President, Lord Chiang), in which the preceding space serves as an honorific marker for 蔣公. This use is also still current in very formal letters or other old-style documents.
When Chinese is written in transliterated form (as in Hanyu Pinyin), spaces are used to assist in reading. source:http://en.wikipedia.org/wiki/Chinese_punctuation
So its because in chinese as space is used a bit differently than in english.
空格的原因取决于字符,因为在查询部分文本的尺寸时可以找到空格,但这并不能说明为什么标签会简单地忽略此问题。
然而,空间实际上是由 FrameSetter 引入的,为了实现均匀的空间,您可以使用 FrameSetter 获取换行符并使用 TypeSetter (CTTypesetterCreateWithAttributedString) 生成线条并将它们指向所需的线条距离,如<一href="https://developer.apple.com/library/ios/#documentation/StringsTextFonts/Conceptual/CoreText_Programming/Operations/Operations.html#//apple_ref/doc/uid/TP40005533-CH4-SW16" rel="nofollow ">Apple 的手动换行。正如我简要检查过的那样,这也适用于您给定的示例。
不管怎样,我只能同意这个标签的行为有点奇怪,但也没有那么糟糕,因为它看起来更好。
The reason for the space is depending on the characters, as it could be found when querying parts of the text for its dimension, but this does not declare why a label simply ignores this problem.
However the space is in fact introduced by the FrameSetter in order to achieve even space you could use the FrameSetter to get the line breaks and use a TypeSetter (CTTypesetterCreateWithAttributedString) to produce the lines and point them at a desired line distance, as shown in the Manual Line Break from Apple. This also works for your given sample, as i have briefly checked.
Anyway I could only agree that the behaviour of the label is somehow odd, but not this bad as it looks better.
终于得到了苹果工程师的官方答复:
I finally got an official answer from Apple engineer: