iOS:sizeWithFont对于单个字符是不同于字符串?

时间:2012-12-07 15:16:57

标签: ios position width uilabel character

我正在尝试确定UILabel中角色的准确位置,比如说:

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

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

有没有办法准确确定字符串中单个字形的位置?

非常感谢。

3 个答案:

答案 0 :(得分: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 字符的rect。这样做的原因是,如果换行,firstRectForRange:仅在中断前的第一行返回rect。

另外,如果您需要大量使用它,请考虑将上述方法添加为UITextView类别。不要忘记添加错误处理!

通过阅读Text, Web, and Editing Programming Guide for iOS,您可以了解有关firstRectForRange:如何在幕后工作的更多信息。

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

答案 1 :(得分:0)

好的字体现在每天都很聪明,并且尊重角色在其前身角色中的位置。

以下是关于字母o

的起始位置的示例
NSRange posRange = [hello rangeOfString:@"o"];
NSString *substring = [hello substringToIndex:posRange.location];
CGSize size = [substring sizeWithFont:[UIFont systemFontOfSize:14.0f]];

不能对包含字母o的字符串执行相同的操作,并减去字符串中找不到字母o的大小。 这应该给出一个很好的开头位置的字母和大小。

答案 2 :(得分: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