如何在我绘制文本的自定义视图中使链接、电话号码可点击(与 textview 中的行为相同)?

Posted

技术标签:

【中文标题】如何在我绘制文本的自定义视图中使链接、电话号码可点击(与 textview 中的行为相同)?【英文标题】:How to make link, phone number clickable (Same behaviour as in textview) in a custom view where i draw text? 【发布时间】:2017-11-13 08:48:00 【问题描述】:

我创建了一个视图并在其上绘制文本,我希望如果任何文本包含链接(超链接)或电话号码,它将是可点击的(与文本视图中的行为相同)那么如何实现呢?强>

我在其中绘制文本的视图代码:-

class DrawRectCellView: UIView 

    var text: NSAttributedString?

    override init(frame: CGRect) 
        super.init(frame: frame)

    

    required init(coder aDecoder: NSCoder) 
        fatalError("init(coder:) has not been implemented")
    

    // Only override drawRect: if you perform custom drawing.

    override func draw(_ rect: CGRect)
    
        UIColor.white.setFill()
        UIGraphicsGetCurrentContext()?.fill(rect)

        // Drawing code

        if let attributedText = text 
            attributedText.draw(in: rect)
        
    


表格单元的代码:-

class DrawRectCell: UITableViewCell 

    var cellView: DrawRectCellView?

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) 
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        // Initialization code
        cellView = DrawRectCellView(frame: self.frame)

        if let cell = cellView 
            cell.autoresizingMask = UIViewAutoresizing(rawValue: UIViewAutoresizing.RawValue(UInt8(UIViewAutoresizing.flexibleWidth.rawValue) | UInt8(UIViewAutoresizing.flexibleHeight.rawValue)))
            cell.contentMode = UIViewContentMode.redraw
        

        self.contentView.addSubview(cellView!)
    

    required init(coder aDecoder: NSCoder) 
        fatalError("init(coder:) has not been implemented")
    

    func setTextString(_ text: NSAttributedString) 
        if let view = cellView 
            view.text = text
        
    

    override func awakeFromNib() 
        super.awakeFromNib()
        // Initialization code
    

    override func setSelected(_ selected: Bool, animated: Bool) 
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    

我正在设置文本,例如 = www.google.com 或任何电话号码,它仅显示为普通文本(在 textview 中不显示(使其可点击))

【问题讨论】:

【参考方案1】:

首先你需要像这样检测你的文本是否包含url或数字。

let input = "This is a test with the URL https://www.hackingwithswift.com to be detected."
let detector = try! NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
let matches = detector.matches(in: input, options: [], range: NSRange(location: 0, length: input.utf16.count))

for match in matches 
    guard let range = Range(match.range, in: input) else  continue 
    let url = input[range]
    print(url)

如果您在设置为 textview 后检测到 url,则需要像这样在 UITextView 上添加UITapGestureRecognizer

let tapGesture = UITapGestureRecognizer(target: self, action: "handleTap")  

textview.addGestureRecognizer(tapGesture)

func handleTap(sender: UITapGestureRecognizer) 

    if sender.state == .began 
      //write your code here for url tap 
    

【讨论】:

我没有使用 textview 我正在使用视图和绘图文本,同样的事情适用于视图吗? 是的,你也可以在 uiview 上应用同样的东西。 它会让链接和数字突出显示吗? 当我们在文本视图中选择或点击数字时,苹果提供的默认操作表会显示吗?【参考方案2】:

您可以在 DrawRectCellView 上添加 UITapGestureRecognizer 并将 IndexPath 设置为标签。在 UITapGestureRecognizer 的 selector 方法中,您可以获取被点击的 contentView 包含文本的子视图信息。

【讨论】:

【参考方案3】:

在 TextView 中突出显示某些文本:

假设您有 textView textView,那么您可以使用此代码突出显示 URL、电话号码等:

textView.dataDetectorTypes = [] // doesn't work if textfield isEditable is set to true
textView.linkTextAttributes = [NSForegroundColorAttributeName: UIColor.blue] // the default is blue anyway

如果您只想包含一些特定的要检测的数据类型,请将它们添加到数组中,如下所示:

textView.dataDetectorTypes = [.link]

以下是类型列表:

https://developer.apple.com/documentation/uikit/uidatadetectortypes

使整个视图可点击:

您可以将UITapGestureRecognizer 添加到视图中(如果它不包含电话号码或超链接,则不添加),如下所示:

https://***.com/a/28675664/7270113

此答案可能未使用您正在使用的 Swift 版本。如果是这样,编译器会告诉你如何改变它,所以它会起作用。

如果你不喜欢使用选择器,我推荐使用库Closures https://github.com/vhesener/Closures,特别是这个https://vhesener.github.io/Closures/Extensions/UITapGestureRecognizer.html

【讨论】:

这不是关于 tapGesture 如何使文本看起来像链接(电话号码和超链接)。例如,我们有一个字符串“hello this is an example www.google.com end of example”,如果我们把它放在文本视图中,它会使 www.google.com 突出显示和可点击,当我们点击它时,它将重定向到那个网站所以如何在自定义视图中实现这一点,我在视图上绘制文本。 我没有使用 textview 。我正在使用一个绘制文本的视图,所以下面的代码可以与视图一起使用吗? 如果您将UITextView 作为子视图添加到您的单元格内容视图,您将节省大量时间和头痛。您甚至可以使用UIStackView 来平衡您单元格内的所有内容。为什么要画文字?直接将NSAttributedString 添加到UITextView 并以这种方式配置字体和大小等内容肯定会更容易。如果可以的话,你应该使用 Xcode 和 Swift 已经自带的原生元素。 我正在使用这种方法,因为带有 NsAttributedString 的 UITextView 会降低滚动行为,并且我希望平滑滚动,所以使用这种方法。 那是相当难以实现的。首先,您需要定义一些检测逻辑来遍历您的字符串并转换范围内的字符,这些字符是 URL 等的一部分。这应该是简单的部分,@Shauket Sheikh 的答案显示了如何做到这一点。现在您需要在这些链接上覆盖手势识别器,因此它们只会覆盖文本。这是我能想到的唯一方法。您基本上也必须在正确的位置绘制它们。除非每个绘制的文本只有一个链接。然后你可以让整个视图可点击,但这可能不是一个好的用户体验。

以上是关于如何在我绘制文本的自定义视图中使链接、电话号码可点击(与 textview 中的行为相同)?的主要内容,如果未能解决你的问题,请参考以下文章

如何在绘制之前获取调整大小的自定义视图的宽度和高度

从编辑文本中过滤列表视图

在画布上绘制位图已缩放

在RelativeLayout中部分绘制的自定义视图

在自定义绘制的视图中动画大小变化的问题

使用自定义适配器的自定义对象