如何在UILabel中找到文本子字符串的CGRect?
对于给定的 NSRange
,我想在中找到
对应于 CGRect
UILabel NSRange
的字形。例如,我想在快速的棕色狐狸跳过懒狗这句话中找到 CGRect
,其中包含单词dog。
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."
诀窍是, UILabel
有多行,文字实际上是 attributedText
,所以找到字符串的确切位置有点困难。
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.
我想在 UILabel $ c上写的方法$ c>子类看起来像这样:
The method that I'd like to write on my UILabel
subclass would look something like this:
- (CGRect)rectForSubstringWithRange:(NSRange)range;
详细信息,对于有兴趣的人:
我的目标是能够创建一个具有UILabel精确外观和位置的新UILabel,然后我可以动画。我已经把剩下的想法弄明白了,但特别是这一步让我暂时退缩了。
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.
我是什么到目前为止已尝试解决问题:
- 我希望iOS 7中有一些Text Kit可以解决这个问题,但是我用Text Kit看到的大多数例子都集中在
UITextView
和UITextField
,而不是UILabel
。 - 我在这里看到了Stack Overflow的另一个问题,它承诺解决问题,但是接受的答案已超过两年,代码与属性文本的效果不佳。
- 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
andUITextField
, rather thanUILabel
. - 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.
我是打赌,正确的答案这包括以下之一:
- 使用标准的文本工具包方法在一行代码中解决此问题。我敢打赌它会涉及
NSLayoutManager
和textContainerForGlyphAtIndex:effectiveRange
- 写作一种复杂的方法,可以将UILabel分解为线条,并在线条中查找字形的矩形,可能使用Core Text方法。我目前最好的办法是将 @mattt's 改为 TTTAttributedLabel ,它有一个方法可以在一个点找到一个字形 - 如果我将其反转,并找到一个可能有效的字形点。
- Using a standard Text Kit method to solve this problem in a single line of code. I'd bet it would involve
NSLayoutManager
andtextContainerForGlyphAtIndex: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.
更新:这里有一个github要点,我已经尝试过三件事来解决这个问题: https://gist.github.com/bryanjclark/7036101
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
在代码中 Joshua的答案后,我想出了以下似乎运作良好:
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];
}