gpt4 book ai didi

ios - CATextLayer 上来自 iOS 6 的不需要的垂直填充

转载 作者:可可西里 更新时间:2023-11-01 05:04:07 27 4
gpt4 key购买 nike

背景: 我在 iOS 5 中开始了我的项目,并构建了一个带有图层的漂亮按钮。我在按钮上添加了一个 textLayer 并使用以下代码将其居中:

    float textLayerVerticlePadding = ((self.bounds.size.height - fontSize) /2);
textLayer = [[CATextLayer alloc]init];
[textLayer setFrame:CGRectOffset(self.bounds, 0, textLayerVerticlePadding)];

在 iOS 6 之前,它运行良好并且看起来死板。

问题: iOS 6 在最上面的边界和 textLayer 中的文本之间添加了一个空格(填充)。这扰乱了上面的计算。有没有办法确保 iOS 6 没有?因为我想同时支持 iOS 5 和 6(对于那些喜欢谷歌 map 的人)。

图片:
这是 iOS 5,红色是 textLayer 的背景(为了更明显)

这是 iOS 6


更新: 虽然我确信下面的所有答案在他们自己的方式中都是正确的,但我找到了 t0rst 最简单的执行方法的帖子。 HelveticaNeue 为 iOS5 和 iOS6 都留下了一点空间,不像 Helvetica 在 iOS5 中顶部没有空间,在 iOS6 中空间很小。

更新 2: 玩了一会儿,发现小空间的大小。没有详细说明,空间是字体大小的 1/6。所以为了补偿它我写了
float textLayerVerticlePadding = ((self.bounds.size.height - fontSize) /2) - (fontSize/6);
[textLayer setFrame:CGRectOffset(self.bounds, 0, textLayerVerticlePadding)];

使用该代码,我每次都会陷入僵局。请注意,这仅在 iOS5 和 iOS6 上使用 HelveticaNeue-Bold 进行了测试。我不能说别的。

最佳答案

在 iOS 5 及更早版本中,CATextLayer 中的第一个基线始终位于从 CTLineGetTypographicBounds 获得的上升位置的边界顶部下方,当传递使用第一行的字符串制作的 CTLine 时。

在 iOS 6 中,这不再适用于所有字体。因此,当您定位 CATextLayer 时,您无法再可靠地决定将它放在哪里以获得正确的视觉对齐。或者你可以吗? ...

首先,旁白:不久前在 iOS 5 中尝试计算 CATextLayer 的定位行为时,我尝试使用大写高度、UIFont 的上升等的所有组合,最后发现从 CTLineGetTypographicBounds 上升是我需要的。在这个过程中,我发现 a) 从 UIFont ascenderCTFontGetAscentCTLineGetTypographicBounds 的上升对于某些字体是不一致的,并且 b) 上升经常很奇怪 - 要么裁剪重音,要么在上方留出很多空间。 a) 的解决方案是知道使用哪个值。 b) 除了通过抵消 CATextLayer 边界在上面留下足够的空间之外,没有真正的解决方案,如果它可能会让你的口音被剪掉。

回到 iOS 6。如果您避免使用最糟糕的字体(从 6.0 开始,并且可能会发生变化),您仍然可以使用其余字体对 CATextLayer 进行编程定位。违规者是: AcademyEngravedLetPlain , Courier , HoeflerText Palatino - 从视觉上看,这些系列正确定位(即没有剪裁)在代码中的三个基准源,但不剪裁被放置。 Helvetica .HelveticaNeueUI (又名系统字体)系列在 CATextLayer 给出的上升处与基线正确定位,但其他上升源没有用。

我做过的一些测试示例。示例文本以不同的颜色绘制了 3 次。坐标原点在灰色框的左上角。黑色文本由 UIFont ascender 绘制,从 CTLineDraw 上升向下偏移; CTLineGetTypographicBounds 绘制透明红色,边界等于灰色框;透明蓝色是用 CATextLayer UIKit 添加 NSString 位于灰色框的原点和 drawAtPoint:withFont: 绘制的。

1) 一个表现良好的字体,Copperplate-Light。这三个样本是重合的,呈现栗色,这意味着所有来源的上升都足够接近。 iOS 5 和 6 相同。

2) Courier 在 iOS 5 下。UIFont 将文本定位得太高(红色),但是从 CATextLayer(黑色)上升的 CTLineDraw 匹配 CTLineGetTypographicBounds 定位 - 所以我们可以从那里放置和更正。 CATextLayer(蓝色)放置文本而不剪裁。 ( Helvetica .HelveticaNeueUI 在 iOS 6 中的行为是这样的)

3) Courier 在 iOS 6 下。NSString drawAtPoint:withFont:(红色)现在放置文本使其不被剪裁,但定位不再匹配从 CATextLayer(黑色)或从 CTLineGetTypographicBounds(蓝色)中使用的 UIFont 上升器的上升。这对于程序定位是不可用的。 ( AcademyEngravedLetPlain HoeflerText Palatino 在 iOS 6 中也表现得如此)

希望这有助于避免我经历的一些时间浪费,如果你想深入一点,可以试试这个:

- (NSString*)reportInconsistentFontAscents
{
NSMutableString* results;
NSMutableArray* fontNameArray;
CGFloat fontSize = 28;
NSString* fn;
NSString* sample = @"Éa3Çy";
CFRange range;
NSMutableAttributedString* mas;
UIFont* uifont;
CTFontRef ctfont;
CTLineRef ctline;
CGFloat uif_ascent;
CGFloat ctfont_ascent;
CGFloat ctline_ascent;

results = [NSMutableString stringWithCapacity: 10000];
mas = [[NSMutableAttributedString alloc] initWithString: sample];
range.location = 0, range.length = [sample length];

fontNameArray = [NSMutableArray arrayWithCapacity: 250];
for (fn in [UIFont familyNames])
[fontNameArray addObjectsFromArray: [UIFont fontNamesForFamilyName: fn]];
[fontNameArray sortUsingSelector: @selector(localizedCaseInsensitiveCompare:)];
[fontNameArray addObject: [UIFont systemFontOfSize: fontSize].fontName];
[fontNameArray addObject: [UIFont italicSystemFontOfSize: fontSize].fontName];
[fontNameArray addObject: [UIFont boldSystemFontOfSize: fontSize].fontName];

[results appendString: @"Font name\tUIFA\tCTFA\tCTLA"];

for (fn in fontNameArray)
{
uifont = [UIFont fontWithName: fn size: fontSize];
uif_ascent = uifont.ascender;

ctfont = CTFontCreateWithName((CFStringRef)fn, fontSize, NULL);
ctfont_ascent = CTFontGetAscent(ctfont);

CFAttributedStringSetAttribute((CFMutableAttributedStringRef)mas, range, kCTFontAttributeName, ctfont);
ctline = CTLineCreateWithAttributedString((CFAttributedStringRef)mas);
ctline_ascent = 0;
CTLineGetTypographicBounds(ctline, &ctline_ascent, 0, 0);

[results appendFormat: @"\n%@\t%.3f\t%.3f\t%.3f", fn, uif_ascent, ctfont_ascent, ctline_ascent];

if (fabsf(uif_ascent - ctfont_ascent) >= .5f // >.5 can round to pixel diffs in display
|| fabsf(uif_ascent - ctline_ascent) >= .5f)
[results appendString: @"\t*****"];

CFRelease(ctline);
CFRelease(ctfont);
}

[mas release];

return results;
}

关于ios - CATextLayer 上来自 iOS 6 的不需要的垂直填充,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12567562/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com