iOS:单个字符的 sizeWithFont 与字符串不同?

标签 ios position width uilabel character

我正在尝试确定 UILabel 中字符的精确位置,例如:

(UILabel *)label.text = @"你好!";

我想确定'o'的位置。我认为我可以使用 sizeWithFont 将所有前面的字符(或整个前面的字符串)的宽度相加。我得到的宽度值比它应该的值大了大约 10%。对单个字母的宽度求和(即 [@"H"sizeWithFont...] + [@"e"sizeWithFont...] + l... + l...)比 [@"Hell"sizeWithFont 累积更多的错误...]。

有没有一种方法可以准确地确定字符串中单个字形的位置?

非常感谢。

最佳答案

是的,但不在 UILabel 中,也不使用 sizeWithFont:。
我最近与 Apple Developer Support 合作,显然 sizeWithFont: 实际上是一个近似值。当您的文本 (1) 跨越多行并且 (2) 包含非拉丁字符(即中文、阿拉伯语)时,它会变得不那么准确,这两者都会导致 sizeWithFont: 无法捕获行间距变化。因此,如果您想要 100% 的准确率,请不要依赖此方法。
您可以做以下两件事:
(1) 使用不可编辑的 UITextView 代替 UILabel。这将支持 UITextInput 协议(protocol)方法 firstRectForRange: ,您可以使用它来获取所需字符的矩形。你可以使用这样的方法:

- (CGRect)rectOfCharacterAtIndex:(NSUInteger)characterIndex inTextView:(UITextView *)textView
{
    // set the beginning position to the index of the character
    UITextPosition *beginningPosition = [textView positionFromPosition:textView.beginningOfDocument offset:characterIndex];
    // set the end position to the index of the character plus 1
    UITextPosition *endPosition = [textView positionFromPosition:beginningPosition offset:1];
    // get the text range between these two positions
    UITextRange *characterTextRange = [textView textRangeFromPosition:beginningPosition toPosition:endPosition]];
    // get the rect of the character
    CGRect rectOfCharacter = [textView firstRectForRange:characterTextRange];
    // return the rect, converted from the text input view (unless you want it to be relative the text input view)
    return [textView convertRect:rectOfCharacter fromView:textView.textInputView];
}
要使用它(假设屏幕上已经有一个名为 myTextView 的 UITextView),您可以这样做:
myTextView.text = @"Hello!";
CGRect rectOfOCharacter = [self rectOfCharacterAtIndex:4 inTextView:myTextView];
// do whatever you need with rectOfOCharacter
仅使用此方法确定 ONE 字符的矩形。原因是在换行的情况下, firstRectForRange: 只返回第一行的矩形,在换行之前。
另外,如果您要经常使用它,请考虑将上述方法添加为 UITextView 类别。不要忘记添加错误处理!
您可以通过阅读 Text, Web, and Editing Programming Guide for iOS 了解有关 firstRectForRange: 如何“在后台”工作的更多信息。 .
(2) 通过继承 UIView 并使用 Core Text 渲染字符串来创建自己的 UILabel。由于您正在进行渲染,因此您将能够获得字符的位置。这种方法需要做很多工作,只有在你真的需要它时才值得(当然,我不知道你的应用程序的其他需求)。如果您不确定这将如何工作,我建议使用第一种方法。

关于iOS:单个字符的 sizeWithFont 与字符串不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13765875/

相关文章:

ios - MonoTouch - 在没有 Xib 的情况下创建 UI

ios - Flowplayer Flash 覆盖功能和 ios 兼容性

iOS 13 UISplitViewController 内的 UITabBarController 未正确折叠

position - 使用加速度计和陀螺仪计算位移 (MPU6050)

javascript - 如何获取类名每个元素的偏移位置?

css - 单击时选择 div 中的所有内容?/调整文本框大小以适合文本?

ios - 在 XCode 和 IOS 7 中移动文件

html - 当我调整浏览器大小时图像移动了位置?

wpf - 如何使 WPF 列表框中的列中所有项目的宽度相同?

html - 如何使包装内的图像跨越包装的整个宽度