ios - iOS 8.1 中的 UITextField 在使用某些字体时在编辑模式和非编辑模式之间具有不同的垂直文本对齐方式

标签 ios objective-c ios8 uitextview

当使用 Helvetica Neue Light 17 等字体时,iOS 8.1.X 中的 UITextField 在编辑模式和非编辑模式之间具有不同的垂直文本对齐方式:

UITextField bug example

我有一个示例项目 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/

相关文章:

iOS8/模拟器 - SFHFKeychainUtils 错误,SFHFKeychainUtilsErrorDomain 错误 -34018

ios - 图像未按尺寸显示

iOS 相机权限不会出现在某些设备的设置下

iphone - 字符串到 NSDate 然后返回到字符串

objective-c - 两个 UILabels 在彼此下面,隐藏最上面的一个

ios - 使用 IB 自定义 TableView 标题

IOS 5.0 越狱如何自定义/屏蔽横幅通知

iOS/Xcode : How to simulate network connection between two iOS simulators

ios - 长时间隐藏 View

ios8 - Xcode 6 NSUserDefaults 不起作用