当使用 Helvetica Neue Light 17 等字体时,iOS 8.1.X 中的 UITextField 在编辑模式和非编辑模式之间具有不同的垂直文本对齐方式:
我有一个示例项目 here .
是否有不需要创建自定义文本字段的解决方法? 主要问题是当使用动态类型时,字体会在运行时发生变化。
反正我开了个雷达rdar://19374610 .
最佳答案
只是偶然发现了同样的问题,并决定稍微“调试”一下。基本上,我只是绘制了各种字体的值(大写高度、磅值、首选高度、可用高度、文本移动的距离)并注意到了一种模式。
文本向上移动的原因是它以两种完全不同的方式呈现:非编辑版本使用 -drawRect:
呈现(您甚至可以覆盖钩子(Hook)),编辑版本是由所谓的 UIFieldEditor
呈现。无论您是否在 Retina 设备上,这一个都会ceil
文本高度,然后将其居中。但是,在 Retina 设备上,您应该始终使用 ceil(scalar * scale)/scale
对齐像素。因此 iOS 假定文本高度比需要的高,并将其向上移动一点以保持其居中。有趣的是,静态文本的呈现和 UIFieldEditor
不同。
要解决此问题,子类化 UITextField
并覆盖 -editingRectForBounds:
。在这里,您需要使用非编辑矩形(“文本矩形”)并说明 Apple 将提前执行的转换。
- (CGRect)editingRectForBounds:(CGRect)bounds
{
if (UIDevice.currentDevice.systemVersion.integerValue != 8) return [self textRectForBounds:bounds];
CGFloat const scale = UIScreen.mainScreen.scale;
CGFloat const preferred = self.attributedText.size.height;
CGFloat const delta = ceil(preferred) - preferred;
CGFloat const adjustment = floor(delta * scale) / scale;
CGRect const textRect = [self textRectForBounds:bounds];
CGRect const editingRect = CGRectOffset(textRect, 0.0, adjustment);
return editingRect;
}
编辑:我刚刚在较旧的操作系统版本(包括 8.0.0)上测试了代码。在 iOS 7.x 上,一切似乎都很好,iOS 8.0 已经包含该错误。我们无法预测 future ,所以现在我只包含针对 iOS 8.x 的修复,希望 Apple 自己修复 iOS 9 中的问题。
另一个编辑:此代码使编辑文本出现在与其静态文本相同的位置。如果您想单独控制它们(Apple 认为这是有道理的,因为它们同时提供 -textRectForBounds:
和 -editingRectForBounds:
),您可能需要替换 [ self textRectForBounds:bounds]
和 [super editingRectForBounds:bounds]
。如果您想使用 swizzling 在类别中实现此修复,您当然应该使用 super
版本。
关于ios - iOS 8.1 中的 UITextField 在使用某些字体时在编辑模式和非编辑模式之间具有不同的垂直文本对齐方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27784822/