我有一个问题,boundingRectForGlyphRange
总是返回CGRect.zero
“0.0,0.0,0.0,0.0”。
例如,我正在编写触及UILabel
特性的部分文本的代码。我的文本的第一部分是任何文本,第二部分是阅读更多。
我希望点击识别器只在我触摸READ MORE时工作。如果我触摸UILabel
上的任何点,CGRectContainsPoint
总是返回true
,然后调用该操作。
这里我的代码:
override func viewDidLoad() {
super.viewDidLoad()
// The full string
let firstPart:NSMutableAttributedString = NSMutableAttributedString(string: "Lorem ipsum dolor set amit ", attributes: [NSFontAttributeName: UIFont.systemFontOfSize(13)])
firstPart.addAttribute(NSForegroundColorAttributeName, value: UIColor.blackColor(),
range: NSRange(location: 0, length: firstPart.length))
info.appendAttributedString(firstPart)
// The "Read More" string that should be touchable
let secondPart:NSMutableAttributedString = NSMutableAttributedString(string: "READ MORE", attributes: [NSFontAttributeName: UIFont.systemFontOfSize(14)])
secondPart.addAttribute(NSForegroundColorAttributeName, value: UIColor.blackColor(),
range: NSRange(location: 0, length: secondPart.length))
info.appendAttributedString(secondPart)
lblTest.attributedText = info
// Store range of chars we want to detect touches for
moreStringRange = NSMakeRange(firstPart.length, secondPart.length)
print("moreStringRange\(moreStringRange)")
tapRec.addTarget(self, action: "didTap:")
lblTest.addGestureRecognizer(tapRec)
}
func didTap(sender:AnyObject) {
// Storage class stores the string, obviously
let textStorage:NSTextStorage = NSTextStorage(attributedString: info)
// The storage class owns a layout manager
let layoutManager:NSLayoutManager = NSLayoutManager()
textStorage.addLayoutManager(layoutManager)
// Layout manager owns a container which basically
// defines the bounds the text should be contained in
let textContainer:NSTextContainer = NSTextContainer(size: lblTest.frame.size)
textContainer.lineFragmentPadding = 0
textContainer.lineBreakMode = lblTest.lineBreakMode
// Begin computation of actual frame
// Glyph is the final display representation
var glyphRange = NSRange()
// Extract the glyph range
layoutManager.characterRangeForGlyphRange(moreStringRange!, actualGlyphRange: &glyphRange)
// Compute the rect of glyph in the text container
print("glyphRange\(glyphRange)")
print("textContainer\(textContainer)")
let glyphRect:CGRect = layoutManager.boundingRectForGlyphRange(glyphRange, inTextContainer: textContainer)
// Final rect relative to the textLabel.
print("\(glyphRect)")
// Now figure out if the touch point is inside our rect
let touchPoint:CGPoint = tapRec.locationOfTouch(0, inView: lblTest)
if CGRectContainsPoint(glyphRect, touchPoint) {
print("User tapped on Read More. So show something more")
}
}
}
9条答案
按热度按时间ergxz8rk1#
swift 4.2请在此处查找获取
Label
的特定文本action
的解决方案。1.标签声明
1.将属性化文本设置为标签
它看起来像上面的图像。
1.将
tapLabel
操作方法添加到控制器1.添加
UITapGestureRecognizer
扩展名确保执行以下操作:
9o685dep2#
在使用了很多不同的库等之后,我发现了一个有趣的解决方案:http://samwize.com/2016/03/04/how-to-create-multiple-tappable-links-in-a-uilabel/
它将扩展UITapGestureRegonizer并检测触发时拍子是否在字符串的范围内。
以下是此扩展的Swift 4更新版本:
要简化范围转换,还需要此Range扩展
拥有此扩展后,您可以将轻按手势添加到标签:
下面是处理点击的函数:
bfnvny8b3#
若要启用多行可点击且不想子类化UILabel,请执行以下操作:
*为UITapGestureRecognizer编写扩展函数
*配置您的UILable
*添加手势识别选择器功能:
bqucvtff4#
对于任何愿意使用textView的人来说,这是一个真实的简单的选择。我知道这个问题是关于UILabel的,但是如果你读了一些答案的评论,它们对一些人不起作用,而且其中一些非常重的代码对初学者来说不是很好。如果你愿意用UITextView替换UILabel,你可以通过11个简单的步骤来完成。
您可以使用
NSMutableAttributedString
和UITextView
。UITextView有一个委托方法:func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool { ... }
。一旦设置了要使其可点击的字符串部分,委托方法将激活它。这11个步骤列在每段代码上方的注解中。
tvokkenx5#
对于多行标签,您必须设置textStorage字体,否则将返回不正确的范围
这个问题有很多答案。但是,有很多人抱怨点击多行标签失败,这对本页上的大多数答案都是正确的。点击返回的范围不正确,因为
textStorage
没有正确的字体。您可以通过向
textStorage
示例添加正确的字体来快速修复此问题:把所有这些放在一起,你会得到这样的结果:
xnifntxz6#
Swift 3.我开发了一个扩展:
现在我可以检查点击的字符是否在范围内:
dz6r00yl7#
您的文本工具包堆栈出错。您忘记将文本容器添加到布局管理器!因此没有要布局的文本,并且布局管理器无法报告任何字形矩形。因此字形矩形是NSRectZero,这就是为什么您无法报告其中的点击。
另一个问题是,您在应该调用
glyphRangeForCharacterRange
的时候调用了characterRangeForGlyphRange
,并且您似乎不知道如何使用结果(实际上,您丢弃了结果)。下面的代码只显示了使用文本堆栈的部分。我从字符串“Hello to you”开始。我将展示如何学习“to”的矩形位置:
结果是
{x 30.68 y 0 w 10.008 h 13.8}
。现在我们可以继续测试点击是否在那个矩形中。Go Ye And Do Same.xghobddn8#
同意第一票的答案。但是这个答案适用于center textAlignment,当你的UILabel的textAlignment不是center,而且你的UILabel有edgetInset时,你需要修改一些计算代码。我的帖子的答案考虑了textAlignment和edgetInset。
还有一种情况需要考虑。如果你的文本是“magina:linkedword”,“magina”部分是普通文本,“linkedword”是链接。当你为UILabel设置文本时,你需要连接文本和一个空格,否则当你点击标签的结尾时,函数'didTapAttributedTextInLabel'将返回true,但它实际上超出了文本。
3zwtqj6y9#
我开发了这个小型iOS库SmartString,您可以使用它来处理UILabel中特定子字符串上的Taps。
用法: