如何在 UILabel 中找到文本子字符串的 CGRect? [英] How do I locate the CGRect for a substring of text in a UILabel?

查看:15
本文介绍了如何在 UILabel 中找到文本子字符串的 CGRect?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于给定的 NSRange,我想在 UILabel 中找到一个 CGRect 对应于该 的字形NSR 范围.例如,我想在句子The quick brown fox jumps over the lazy dog"中找到包含单词dog"的CGRect.

诀窍是,UILabel 有多行,而且文本实际上是attributedText,所以要找到字符串的确切位置有点困难.>

我想在我的 UILabel 子类上编写的方法看起来像这样:

 - (CGRect)rectForSubstringWithRange:(NSRange)range;

<小时>

详情,给有兴趣的人:

我的目标是能够使用 UILabel 的确切外观和位置创建一个新的 UILabel,然后我可以制作动画.我已经弄清楚了其余部分,但它是尤其是这一步阻碍了我.

到目前为止我为尝试解决问题所做的工作:

  • 我希望在 iOS 7 中会有一些 Text Kit 来解决这个问题,但我在 Text Kit 中看到的大多数例子都集中在 UITextViewUITextField,而不是 UILabel.
  • 我在此处看到 Stack Overflow 上的另一个问题,该问题有望解决该问题,但已接受的答案已超过两年,并且代码在处理属性文本时表现不佳.

我敢打赌,正确答案涉及以下之一:

  • 使用标准的 Text Kit 方法在一行代码中解决这个问题.我敢打赌它会涉及 NSLayoutManagertextContainerForGlyphAtIndex:effectiveRange
  • 编写一个复杂的方法,将 UILabel 分成几行,并在一行中查找字形的矩形,可能使用 Core Text 方法.我目前最好的选择是拆开 @mattt's 优秀的 TTTAttributedLabel,它有一个方法可以在某个点找到一个字形 - 如果我反转它,并找到一个字形的点,那可能会起作用.
<小时>

更新:这是一个 github 要点,其中包含我迄今为止尝试解决此问题的三件事:https://gist.github.com/bryanjclark/7036101

解决方案

在代码中遵循 Joshua 的回答,我提出了以下内容似乎运行良好:

- (CGRect)boundingRectForCharacterRange:(NSRange)range{NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:[self attributesText]];NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];[textStorage addLayoutManager:layoutManager];NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:[self bounds].size];textContainer.lineFragmentPadding = 0;[layoutManager addTextContainer:textContainer];NSRange 字形范围;//转换字形的范围.[layoutManager characterRangeForGlyphRange:range actualGlyphRange:&glyphRange];返回 [layoutManager boundingRectForGlyphRange:glyphRange inTextContainer:textContainer];}

For a given NSRange, I'd like to find a CGRect in a UILabel that corresponds to the glyphs of that NSRange. For example, I'd like to find the CGRect that contains the word "dog" in the sentence "The quick brown fox jumps over the lazy dog."

The trick is, the UILabel has multiple lines, and the text is really attributedText, so it's a bit tough to find the exact position of the string.

The method that I'd like to write on my UILabel subclass would look something like this:

 - (CGRect)rectForSubstringWithRange:(NSRange)range;


Details, for those who are interested:

My goal with this is to be able to create a new UILabel with the exact appearance and position of the UILabel, that I can then animate. I've got the rest figured out, but it's this step in particular that's holding me back at the moment.

What I've done to try and solve the issue so far:

  • I'd hoped that with iOS 7, there'd be a bit of Text Kit that would solve this problem, but most every example I've seen with Text Kit focuses on UITextView and UITextField, rather than UILabel.
  • I've seen another question on Stack Overflow here that promises to solve the problem, but the accepted answer is over two years old, and the code doesn't perform well with attributed text.

I'd bet that the right answer to this involves one of the following:

  • Using a standard Text Kit method to solve this problem in a single line of code. I'd bet it would involve NSLayoutManager and textContainerForGlyphAtIndex:effectiveRange
  • Writing a complex method that breaks the UILabel into lines, and finds the rect of a glyph within a line, likely using Core Text methods. My current best bet is to take apart @mattt's excellent TTTAttributedLabel, which has a method that finds a glyph at a point - if I invert that, and find the point for a glyph, that might work.

Update: Here's a github gist with the three things I've tried so far to solve this issue: https://gist.github.com/bryanjclark/7036101

解决方案

Following Joshua's answer in code, I came up with the following which seems to work well:

- (CGRect)boundingRectForCharacterRange:(NSRange)range
{
    NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:[self attributedText]];
    NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
    [textStorage addLayoutManager:layoutManager];
    NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:[self bounds].size];
    textContainer.lineFragmentPadding = 0;
    [layoutManager addTextContainer:textContainer];

    NSRange glyphRange;

    // Convert the range for glyphs.
    [layoutManager characterRangeForGlyphRange:range actualGlyphRange:&glyphRange];

    return [layoutManager boundingRectForGlyphRange:glyphRange inTextContainer:textContainer];
}

这篇关于如何在 UILabel 中找到文本子字符串的 CGRect?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆