UITextView带有可点击链接但没有文字突出显示
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UITextView带有可点击链接但没有文字突出显示相关的知识,希望对你有一定的参考价值。
我有一个显示不可编辑文本的UITextView。我希望文本能够自动解析用户的链接,电话号码等,以及可点击的文本。
我不希望用户能够突出显示文本,因为我想要覆盖那些长按和双击交互以执行不同的操作。
为了在ios7中解析链接,需要为UITextView打开Selectable开关,但Selectable也可以启用突出显示,这是我不想要的。
我尝试重写长按手势以防止突出显示,但这似乎也禁用了链接上的普通水龙头......
for (UIGestureRecognizer *recognizer in cell.messageTextView.gestureRecognizers) {
if ([recognizer isKindOfClass:[UILongPressGestureRecognizer class]]){
recognizer.enabled = NO;
}
if ([recognizer isKindOfClass:[UITapGestureRecognizer class]]){
recognizer.enabled = YES;
}
}
有很多类似的线程,但似乎没有解决这个特定的链接启用问题,文本不突出显示。
我正在处理完全相同的问题,我能做的最好的事情就是通过将以下内容添加到UITextView的委托来立即清除选择:
- (void)textViewDidChangeSelection:(UITextView *)textView {
if(!NSEqualRanges(textView.selectedRange, NSMakeRange(0, 0))) {
textView.selectedRange = NSMakeRange(0, 0);
}
}
请注意检查以防止递归。这几乎解决了这个问题,因为只有选择被禁用 - 链接仍然有用。
另一个切线问题是文本视图仍然会成为第一响应者,您可以通过在设置所选范围后设置所需的第一响应者来解决此问题。
注意:剩下的唯一视觉怪异是按住并放大放大镜。
我不确定这是否适用于您的特定情况,但我有一个类似的情况,我需要textview链接可点击但不希望文本选择发生,我使用textview在CollectionViewCell中显示数据。
我只需要覆盖-canBecomeFirstResponder
并返回NO
。
@interface MYTextView : UITextView
@end
@implementation MYTextView
- (BOOL)canBecomeFirstResponder {
return NO;
}
@end
正如我在另一篇文章中所写,还有另一种解决方案。
经过几次测试,我找到了解决方案。
如果您希望链接处于活动状态且未启用选择,则需要编辑gestureRecognizers。
例如 - 有3个LongPressGestureRecognizers。一个用于单击链接(minimumPressDuration = 0.12),第二个用于放大可编辑模式(minimumPressDuration = 0.5),第三个用于选择(minimumPressDuration = 0.8)。此解决方案删除LongPressGestureRecognizer以进行选择,其次用于缩放编辑模式。
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上测试过,但它应该适用于所有版本(iOS 7,8,9)。我希望它有所帮助! :)
Swift 4,Xcode 9.2
以下是不同的方法,
class TextView: UITextView {
//MARK: Properties
open var didTouchedLink:((URL,NSRange,CGPoint) -> Void)?
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func draw(_ rect: CGRect) {
super.draw(rect)
}
open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = Array(touches)[0]
if let view = touch.view {
let point = touch.location(in: view)
self.tapped(on: point)
}
}
}
extension TextView {
fileprivate func tapped(on point:CGPoint) {
var location: CGPoint = point
location.x -= self.textContainerInset.left
location.y -= self.textContainerInset.top
let charIndex = layoutManager.characterIndex(for: location, in: self.textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
guard charIndex < self.textStorage.length else {
return
}
var range = NSRange(location: 0, length: 0)
if let attributedText = self.attributedText {
if let link = attributedText.attribute(NSAttributedStringKey.link, at: charIndex, effectiveRange: &range) as? URL {
print("
##-->You just tapped on '(link)' withRange = (NSStringFromRange(range))
")
self.didTouchedLink?(link, range, location)
}
}
}
}
如何使用,
let textView = TextView()//Init your textview and assign attributedString and other properties you want.
textView.didTouchedLink = { (url,tapRange,point) in
//here goes your other logic for successfull URL location
}
这对我有用。
我无法摆脱放大玻璃,但这将允许您保持文本视图可选(因此您可以点击链接),但摆脱所有选择相关的UI。仅在iOS 9上测试过。
小心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
}
如果没有此功能,将禁用选择条和上下文菜单,但仍会在所选文本后面留下彩色背景。此功能摆脱了选择背景。
就像我说的那样,我还没有找到摆脱放大玻璃的方法,但是如果他们在链接之外的任何地方进行长时间点击,一旦放大玻璃消失,就不会留下任何东西。
这几乎解决了这个问题,因为禁用了文本选择并隐藏了放大镜 - 链接仍然有用。
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)
}
}
}
}
}
注意:您可以将识别器替换为所需的识别器,而不是删除。
这是一个UITextView子类方法,它只能识别落在链接文本上的点。
class LinkTextView: UITextView {
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
let tapLocation = point.applying(CGAffineTransform(translationX: -textContainerInset.left, y: -textContainerInset.top))
let characterAtIndex = layoutManager.characterIndex(for: tapLocation, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
let linkAttributeAtIndex = textStorage.attribute(.link, at: characterAtIndex, effectiveRange: nil)
// Returns true for points located on linked text
return linkAttributeAtIndex != nil
}
override func becomeFirstResponder() -> Bool {
// Returning false disables double-tap selection of link text
return false
}
}
虽然面对未来可能的实施变化,它确实是脆弱的,但KubíkKašpar的方法是唯一对我有用的方法。
但是(a)如果你继承qazxswpoi这个可以变得更简单,而(b)如果你想要允许的唯一互动是链接点击,你可以立即识别出来:
UITextView
以上是关于UITextView带有可点击链接但没有文字突出显示的主要内容,如果未能解决你的问题,请参考以下文章
iOS UITextView 或 UILabel 带有可点击的动作链接[重复]
如何在 Swift 中制作一个单词可点击的 UITextView?
iOS 7 + Calabash:带有 NSLinkAttributeName 的 UITextView 和链接上的可访问性不起作用