bry*_*ark 69 uilabel ios ios7 textkit
对于给定的NSRange,我想找到一个CGRect在UILabel对应的的字形NSRange.例如,我想CGRect在"快速的棕色狐狸跳过懒狗"这句话中找到包含"狗"字样的字样.

诀窍是,UILabel有多行,而文本确实attributedText如此,所以找到字符串的确切位置有点困难.
我想在我的UILabel子类上写的方法看起来像这样:
- (CGRect)rectForSubstringWithRange:(NSRange)range;
Run Code Online (Sandbox Code Playgroud)
细节,对于有兴趣的人:
我的目标是能够创建一个具有UILabel的确切外观和位置的新UILabel,然后我可以制作动画.我已经把剩下的事情搞清楚了,但特别是这一步让我暂时退缩了.
到目前为止我尝试解决问题的方法是:
UITextView和UITextField而不是UILabel.我敢打赌,对此的正确答案涉及以下其中一项:
NSLayoutManager和textContainerForGlyphAtIndex:effectiveRange更新:这是一个github要点,我已经尝试了迄今为止解决这个问题的三件事:https://gist.github.com/bryanjclark/7036101
Luk*_*ers 88
- (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];
}
Run Code Online (Sandbox Code Playgroud)
Noo*_*ath 16
建立卢克罗杰斯的答案,但写得很快:
斯威夫特2
extension UILabel {
func boundingRectForCharacterRange(_ range: NSRange) -> CGRect? {
guard let attributedText = attributedText else { return nil }
let textStorage = NSTextStorage(attributedString: attributedText)
let layoutManager = NSLayoutManager()
textStorage.addLayoutManager(layoutManager)
let textContainer = NSTextContainer(size: bounds.size)
textContainer.lineFragmentPadding = 0.0
layoutManager.addTextContainer(textContainer)
var glyphRange = NSRange()
// Convert the range for glyphs.
layoutManager.characterRangeForGlyphRange(range, actualGlyphRange: &glyphRange)
return layoutManager.boundingRectForGlyphRange(glyphRange, inTextContainer: textContainer)
}
}
Run Code Online (Sandbox Code Playgroud)
用法示例(Swift 2)
let label = UILabel()
let text = "aa bb cc"
label.attributedText = NSAttributedString(string: text)
let sublayer = CALayer()
sublayer.borderWidth = 1
sublayer.frame = label.boundingRectForCharacterRange(NSRange(text.range(of: "bb")!, in: text))
label.layer.addSublayer(sublayer)
Run Code Online (Sandbox Code Playgroud)
斯威夫特3/4
extension UILabel {
func boundingRect(forCharacterRange range: NSRange) -> CGRect? {
guard let attributedText = attributedText else { return nil }
let textStorage = NSTextStorage(attributedString: attributedText)
let layoutManager = NSLayoutManager()
textStorage.addLayoutManager(layoutManager)
let textContainer = NSTextContainer(size: bounds.size)
textContainer.lineFragmentPadding = 0.0
layoutManager.addTextContainer(textContainer)
var glyphRange = NSRange()
// Convert the range for glyphs.
layoutManager.characterRange(forGlyphRange: range, actualGlyphRange: &glyphRange)
return layoutManager.boundingRect(forGlyphRange: glyphRange, in: textContainer)
}
}
Run Code Online (Sandbox Code Playgroud)
用法示例(Swift 3/4)
let label = UILabel()
let text = "aa bb cc"
label.attributedText = NSAttributedString(string: text)
let sublayer = CALayer()
sublayer.borderWidth = 1
sublayer.frame = label.boundingRect(forCharacterRange: NSRange(text.range(of: "bb")!, in: text))
label.layer.addSublayer(sublayer)
Run Code Online (Sandbox Code Playgroud)
Jos*_*hua 11
我的建议是使用Text Kit.遗憾的是,我们无法访问使用的布局管理器,UILabel但是可以创建它的副本并使用它来获取范围的矩形.
我的建议是创建一个NSTextStorage对象,其中包含与标签中完全相同的属性文本.接下来创建一个NSLayoutManager并将其添加到文本存储对象.最后创建一个NSTextContainer与标签大小相同的文件并将其添加到布局管理器中.
现在文本存储与标签具有相同的文本,文本容器与标签的大小相同,因此我们应该能够询问我们为我们的范围使用的rect创建的布局管理器boundingRectForGlyphRange:inTextContainer:.确保首先使用glyphRangeForCharacterRange:actualCharacterRange:布局管理器对象将字符范围转换为字形范围.
一切顺利,应该给你一个你在标签中指定的范围的边界 CGRect.
我没有对此进行过测试,但这将是我的方法,并通过模仿UILabel自身的工作原理应该有很大的成功机会.
小智 5
swift 4 解决方案,甚至适用于多行字符串,边界被替换为内在内容大小
extension UILabel {
func boundingRectForCharacterRange(range: NSRange) -> CGRect? {
guard let attributedText = attributedText else { return nil }
let textStorage = NSTextStorage(attributedString: attributedText)
let layoutManager = NSLayoutManager()
textStorage.addLayoutManager(layoutManager)
let textContainer = NSTextContainer(size: intrinsicContentSize)
textContainer.lineFragmentPadding = 0.0
layoutManager.addTextContainer(textContainer)
var glyphRange = NSRange()
layoutManager.characterRange(forGlyphRange: range, actualGlyphRange: &glyphRange)
return layoutManager.boundingRect(forGlyphRange: glyphRange, in: textContainer)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
22977 次 |
| 最近记录: |