你如何使文本中的UITextView检测链接部分,仍然有userInteractionDisabled?
我有一个textView分层的tableView细胞。 我需要用户点击tableView行来打开一个viewController,但如果textView有一个链接,它必须是可点击的,就是这样,没有复制,select等
如果我允许这样的用户交互:
textView.userInteractionEnabled=NO; textView.dataDetectorTypes =UIDataDetectorTypeLink;
didSelectRowAtIndexPath
不被调用,我明白为什么,但如何实现呢?
编辑:
我正在寻找的是能够具体确定链接,并允许用户点击链接打开浏览器,并禁用textView的其余部分的交互。 如上所述,整行也应该是可点击的。
附加是我的tableView单元格行的图像,显示链接被检测到,交互也是可能的,但是这将禁用didSelectRowAtIndexPath
区域内的didSelectRowAtIndexPath
。
一个可能的(也是复杂的)解决scheme是在你的UITextView
使用UITapGestureRecogniser
和UITapGestureRecogniser
。
-
首先,你需要find链接的
NSRange
。 -
将
NSRange
转换为UITextRange
-
使用与以下类似的代码在
UITextView
中的链接文本上添加一个UITapGestureRecogniser
。UITextPosition *pos = textView.endOfDocument;// textView ~ UITextView for (int i = 0; i < words*2 - 1; i++){// *2 since UITextGranularityWord considers a whitespace to be a word UITextPosition *pos2 = [textView.tokenizer positionFromPosition:pos toBoundary:UITextGranularityWord inDirection:UITextLayoutDirectionLeft]; UITextRange *range = [textView textRangeFromPosition:pos toPosition:pos2]; CGRect resultFrame = [textView firstRectForRange:(UITextRange *)range ]; UIView* tapViewOnText = [[UIView alloc] initWithFrame:resultFrame]; [tapViewOnText addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(targetRoutine)]]; tapViewOnText.tag = 125; [textView addSubview:tapViewOnText]; [tapViewOnText release]; pos = pos2;
}
我在这段代码中做了什么,得到了相关文本的firstRectForRange
,得到它的firstRectForRange
并在它firstRectForRange
添加了一个透明的可点击的UIView
。
你将不得不使用一些regEx
得到你的链接的范围,将其转换为UITextRange
,并添加可轻敲的UITextRange
。 如果在单个textView
视图中可能存在多个链接,则可以为与其“链接”相对应的每个视图添加一个tag
,并通过检查标记来打开目标方法中的链接。
注意:如果你的UITextView
是普遍不可编辑的,你可能想尝试TTTAttributedLabel
。 这就是我在我的UITableViewCells
所做的
也许它会为你的目的确定:
textView.editable=NO; textView.userInteractionEnabled=YES; textView.dataDetectorTypes =UIDataDetectorTypeLink;
但实际上UITextView在内部使用了UIWebView部件,这种方式可能会在表格单元格中缓慢。
我可以build议使用CoreText
或NSAttributedString
的触摸。 例如,你可以阅读这个SOpost 。
如果你正在尝试添加一个UITextView链接到一个单元格,并且希望didSelectRow在用户点击除链接之外的任何东西时被调用,那么你应该使用hitTest:withEvent:
Swift 3
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { // location of the tap var location = point location.x -= self.textContainerInset.left location.y -= self.textContainerInset.top // find the character that's been tapped let characterIndex = self.layoutManager.characterIndex(for: location, in: self.textContainer, fractionOfDistanceBetweenInsertionPoints: nil) if characterIndex < self.textStorage.length { // if the character is a link, handle the tap as UITextView normally would if (self.textStorage.attribute(NSLinkAttributeName, at: characterIndex, effectiveRange: nil) != nil) { return self } } // otherwise return nil so the tap goes on to the next receiver return nil }
我写了一篇关于这个更详细的文章 。