UITextView与可点击链接,但没有文字突出显示

我有一个UITextView显示不可编辑的文本。 我希望文本自动parsing用户的链接,电话号码等,并为那些可点击。

我不希望用户能够突出显示文本,因为我想覆盖那些长按和双击交互来做不同的事情。

为了在iOS7中parsing链接,需要为UITextView打开“select”开关,但“select”也可以突出显示,这是我不想要的。

我试图覆盖LongPress手势,以防止突出显示,但似乎已禁用链接以及普通的水龙头…

for (UIGestureRecognizer *recognizer in cell.messageTextView.gestureRecognizers) { if ([recognizer isKindOfClass:[UILongPressGestureRecognizer class]]){ recognizer.enabled = NO; } if ([recognizer isKindOfClass:[UITapGestureRecognizer class]]){ recognizer.enabled = YES; } } 

有很多类似的线程,但似乎没有解决这个具体问题的链接启用,文字不highlightable。

我正在研究完全相同的问题,而我所能做的最好的办法就是在UITextView的委托中添加以下内容,立即清除select:

 - (void)textViewDidChangeSelection:(UITextView *)textView { if(!NSEqualRanges(textView.selectedRange, NSMakeRange(0, 0))) { textView.selectedRange = NSMakeRange(0, 0); } } 

注意检查以防止recursion。 这几乎解决了这个问题,因为只有select被禁用 – 链接仍然可以工作。

另一个切线问题是,文本视图仍然会成为第一响应者,您可以通过设置所需的第一响应者设置所选范围后修复。

注意:唯一遗留下来的是视觉上的怪异现象,那就是按住了放大镜。

我不知道这是否适用于您的具体情况,但我有一个类似的情况下,我需要textview链接是可点击的,但不希望文本select发生,我使用textview呈现在一个CollectionViewCell中的数据。

我只需要重写-canBecomeFirstResponder并返回NO

 @interface MYTextView : UITextView @end @implementation MYTextView - (BOOL)canBecomeFirstResponder { return NO; } @end 

正如我在另一篇文章中写的,还有另外一个解决scheme。

经过几次testing,我find了解决办法。

如果您希望链接处于活动状态,并且不会启用select,则需要编辑gestureRecognizers。

例如 – 有3个LongPressGestureRecognizers。 一个用于点击链接(minimumPressDuration = 0.12),第二个用于放大可编辑模式(minimumPressDuration = 0.5),第三个用于select(minimumPressDuration = 0.8)。 此解决scheme删除LongPressGestureRecognizerselect,第二个放大编辑模式。

 NSArray *textViewGestureRecognizers = self.captionTextView.gestureRecognizers; NSMutableArray *mutableArrayOfGestureRecognizers = [[NSMutableArray alloc] init]; for (UIGestureRecognizer *gestureRecognizer in textViewGestureRecognizers) { if (![gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]) { [mutableArrayOfGestureRecognizers addObject:gestureRecognizer]; } else { UILongPressGestureRecognizer *longPressGestureRecognizer = (UILongPressGestureRecognizer *)gestureRecognizer; if (longPressGestureRecognizer.minimumPressDuration < 0.3) { [mutableArrayOfGestureRecognizers addObject:gestureRecognizer]; } } } self.captionTextView.gestureRecognizers = mutableArrayOfGestureRecognizers; 

在iOS 9上testing,但它应该适用于所有版本(iOS 7,8,9)。 我希望它有帮助! 🙂

这是为我工作的。

我无法摆脱放大镜,但这将允许您保持文本视图可选(所以你可以点击链接),但摆脱所有select相关的用户界面。 只在iOS 9上testing过。

谨慎Swift下面!

首先, UITextView子类包含这个函数:

 override func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool { return false } 

这将禁用复制等菜单。 然后我包括一个设置方法,我从init调用,在那里做一堆安装相关的任务。 (我只使用故事板中的这些文本视图,因此解码器初始化):

 required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) setup() } private func setup() { selectable = true editable = false tintColor = UIColor.clearColor() } 

Selectable = true以保持链接可点击,editable = false,因为链接在可编辑文本视图中不可点击。 指定一个清晰的tintColor隐藏出现在选区开头和结尾处的蓝条。

最后,在使用子文本视图的控制器中,确保包含UITextViewDelegate协议,委托设置为textView.delegate = self ,并实现这个委托函数:

 func textViewDidChangeSelection(textView: UITextView) { var range = NSRange() range.location = 0 range.length = 0 textView.selectedRange = range } 

如果没有此function,select栏和上下文菜单将被禁用,但彩色背景仍将留在您select的文本后面。 这个function摆脱了select的背景。

就像我说的,我没有find摆脱放大镜的方法,但是如果他们在连接的任何地方进行长时间的敲击,一旦放大镜消失,什么都不会留下。

这几乎解决了文本select被禁用的问题,并隐藏放大镜 – 链接仍然工作。

 func textViewDidChangeSelection(_ textView: UITextView) { if let gestureRecognizers = textView.gestureRecognizers { for recognizer in gestureRecognizers { if recognizer is UILongPressGestureRecognizer { if let index = textView.gestureRecognizers?.index(of: recognizer) { textView.gestureRecognizers?.remove(at: index) } } } } } 

注意:除了删除之外,您可以将识别器replace为所需的识别器。

虽然面对未来可能的实施变化,但是肯定是脆弱的,但KubíkKašpar的方法是唯一为我工作的方法。

但是(a)如果你UITextView ,这个可以变得更简单,而且(b)如果你想要允许的唯一交互是链接攻击,那么你可以立即识别出攻击:

 @interface GMTextView : UITextView @end @implementation GMTextView - (void)addGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer { // discard all recognizers but the one that activates links, by just not calling super // (in iOS 9.2.3 a short press for links is 0.12s, long press for selection is 0.75s) if ([gestureRecognizer isMemberOfClass:UILongPressGestureRecognizer.class] && ((UILongPressGestureRecognizer*)gestureRecognizer).minimumPressDuration < 0.25) { ((UILongPressGestureRecognizer*)gestureRecognizer).minimumPressDuration = 0.0; [super addGestureRecognizer:gestureRecognizer]; } } @end 

这里有一个UITextView子类的方法,它将分析它的手势识别器,只允许那些与链接文本交互(使用Swift 3)。

 class LinkTextView: UITextView { override func gestureRecognizerShouldBegin(_ gesture: UIGestureRecognizer) -> Bool { let tapLocation = gesture.location(in: self).applying(CGAffineTransform(translationX: -textContainerInset.left, y: -textContainerInset.top)) let characterAtIndex = layoutManager.characterIndex(for: tapLocation, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil) let linkAttributeAtIndex = textStorage.attribute(NSLinkAttributeName, at: characterAtIndex, effectiveRange: nil) // Returns true for gestures located on linked text return linkAttributeAtIndex != nil } override func becomeFirstResponder() -> Bool { // Returning false disables double-tap selection of link text return false } }