1

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

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

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

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

非常感谢。

4

3 回答 3

4

是的,但不在 UILabel 中,也不使用 sizeWithFont:。

我最近与 Apple Developer Support 合作,显然 sizeWithFont: 实际上是一个近似值。当您的文本 (1) 跨越多行并且 (2) 包含非拉丁字符(即中文、阿拉伯语)时,它会变得不那么准确,这两者都会导致 sizeWithFont: 无法捕获行间距变化。因此,如果您想要 100% 的准确率,请不要依赖此方法。

您可以做以下两件事:

(1) 使用不可编辑的 UITextView 代替 UILabel。这将支持 UITextInput 协议方法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 类别。不要忘记添加错误处理!

您可以通过阅读适用于 iOS 的文本、Web 和编辑编程指南来了解有关 firstRectForRange: 如何“在后台”工作的更多信息。

(2) 通过继承 UIView 并使用 Core Text 渲染字符串来创建自己的 UILabel。由于您正在进行渲染,因此您将能够获得字符的位置。这种方法需要做很多工作,只有在你真的需要它时才值得(当然,我不知道你的应用程序的其他需求)。如果您不确定这将如何工作,我建议使用第一种方法。

于 2012-12-07T15:54:51.963 回答
0

好吧,字体现在很聪明,并且考虑到字符的位置与其前一个字符。

这是一个关于字母起始位置的示例o

NSRange posRange = [hello rangeOfString:@"o"];
NSString *substring = [hello substringToIndex:posRange.location];
CGSize size = [substring sizeWithFont:[UIFont systemFontOfSize:14.0f]];

不,您可以对包含字母的字符串执行相同的操作,o并减去在没有字母的字符串中找到的大小o。这应该给出字母的一个很好的起始位置和大小。

于 2012-12-07T15:25:50.007 回答
0

在 ios6 中,您可以使用属性字符串

 NSMutableAttributedString *titleText2 = [[NSMutableAttributedString alloc] initWithString:strHello];
    NSRange posRange = [hello rangeOfString:@"o"];


    [titleText2 addAttributes:[NSDictionary dictionaryWithObject:[UIFont systemFontOfSize:14.0f] forKey:NSFontAttributeName] range:NameRange];

并使用此属性字符串设置您的 textView

于 2013-08-06T11:49:44.603 回答