简体   繁体   English

在 UITextview 中点击单词

[英]Get tapped word in a UITextview

I have added a uitextview which is initially non editable.我添加了一个最初不可编辑的 uitextview。 I added a tap gesture which enable the editing to true.我添加了一个点击手势,使编辑成为真。 In the tap gesture selector I get the word that is being tapped.在点击手势选择器中,我得到正在点击的单词。 I have tried a lot many solution but none worked for me as a complete solution.我尝试了很多解决方案,但没有一个作为完整的解决方案对我有用。 Every solution worked if the textview is not scrolled.如果不滚动 textview,则每个解决方案都有效。 But if I scroll the textview the exact word is not retrieved.但是,如果我滚动 textview,则不会检索到确切的单词。 Here is my code for getting the tapped word:这是我获取点击词的代码:

 @objc func handleTap(_ sender: UITapGestureRecognizer) {

    notesTextView.isEditable = true
    notesTextView.textColor = UIColor.white

    if let textView = sender.view as? UITextView {

        var pointOfTap = sender.location(in: textView)
        print("x:\(pointOfTap.x) , y:\(pointOfTap.y)")

        let contentOffsetY = textView.contentOffset.y
        pointOfTap.y += contentOffsetY
        print("x:\(pointOfTap.x) , y:\(pointOfTap.y)")
        word(atPosition: pointOfTap)

 }

func word(atPosition: CGPoint) -> String? {
    if let tapPosition = notesTextView.closestPosition(to: atPosition) {
        if let textRange = notesTextView.tokenizer.rangeEnclosingPosition(tapPosition , with: .word, inDirection: 1) {
            let tappedWord = notesTextView.text(in: textRange)
            print("Word: \(tappedWord)" ?? "")
            return tappedWord
        }
        return nil
    }
    return nil
}

EDITED:编辑:

Here is the demo project with the problem.这是有问题的演示项目。 https://github.com/amrit42087/TextViewDemo https://github.com/amrit42087/TextViewDemo

The best and easiest way in Swift 4 Swift 4 中最好和最简单的方法

METHOD 1:方法一:

Step 1: Add Tap Gesture on the textview第 1 步:在 textview 上添加 Tap Gesture

let tap = UITapGestureRecognizer(target: self, action: #selector(tapResponse(recognizer:)))

textViewTC.addGestureRecognizer(tap)

Step 2: Implement Tap Gesture第 2 步:实施点击手势

@objc func tapResponse(recognizer: UITapGestureRecognizer) {
        let location: CGPoint = recognizer.location(in: textViewTC)
        let position: CGPoint = CGPoint(x: location.x, y: location.y)
        let tapPosition: UITextPosition = textViewTC.closestPosition(to: position)!
        guard let textRange: UITextRange = textViewTC.tokenizer.rangeEnclosingPosition(tapPosition, with: UITextGranularity.word, inDirection: 1) else {return}

        let tappedWord: String = textViewTC.text(in: textRange) ?? ""
        print("tapped word ->", tappedWord)
    }

And yes thats it.是的,就是这样。 Go for it.去吧。

METHOD 2:方法二:

The alternate way is that you can enable links for textview and then set the same as an attribute.另一种方法是您可以为 textview 启用链接,然后将其设置为属性。 Here is an example这是一个例子

var foundRange = attributedString.mutableString.range(of: "Terms of Use") //mention the parts of the attributed text you want to tap and get an custom action
attributedString.addAttribute(NSAttributedStringKey.link, value: termsAndConditionsURL, range: foundRange)

set this attribute text to Textview and textView.delegate = self将此属性文本设置为 Textview 和 textView.delegate textView.delegate = self

Now you just need to handle the response in现在你只需要处理响应

func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {

Hope it helps you.希望对你有帮助。 All the best.一切顺利。

You don't need to add the content offset of the text view.您不需要添加文本视图的内容偏移量。 When you convert location into a scrollview it will already take its content offset into account.当您将位置转换为滚动视图时,它已经将其内容偏移量考虑在内。

Removing:删除:

let contentOffsetY = textView.contentOffset.y
pointOfTap.y += contentOffsetY

should work.应该工作。

Please Try This请试试这个

//add UITextViewDelegate 

    let termsAndConditionsURL = "someText"
        let privacyURL = "SampleText"

        @IBOutlet weak var terms: UITextView!

     override func viewDidLoad() {
            super.viewDidLoad()

            self.terms.delegate = self

    // Adding Attributed text to TextView

            let str = "By registering, you agree to the Terms and the User Privacy Statement."
            let attributedString = NSMutableAttributedString(string: str)
            var foundRange = attributedString.mutableString.range(of: "Terms")
            attributedString.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor.blue, range: foundRange)
            attributedString.addAttribute(NSAttributedStringKey.underlineStyle , value: NSUnderlineStyle.styleSingle.rawValue, range: foundRange)
            attributedString.addAttribute(NSAttributedStringKey.link, value: termsAndConditionsURL, range: foundRange)
            foundRange = attributedString.mutableString.range(of: "User Privacy Statement")
            attributedString.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor.blue, range: foundRange)
            attributedString.addAttribute(NSAttributedStringKey.underlineStyle , value: NSUnderlineStyle.styleSingle.rawValue, range: foundRange)
            attributedString.addAttribute(NSAttributedStringKey.link, value: privacyURL, range: foundRange)
            terms.attributedText = attributedString
            // Do any additional setup after loading the view.
        }


     func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool
        {
            if (URL.absoluteString == termsAndConditionsURL)
            {
    // Perform Terms Action here
            } else if (URL.absoluteString == privacyURL)
            {
    // Perform Terms Action here

            }
            return false
        }

Kunal Gupta's METHOD 1 works for me. Kunal Gupta 的方法 1 对我有用。 Run the code in two funtions just does not work, it may be bug.在两个函数中运行代码不起作用,可能是错误。 I Have report an issue about this situation.我已经报告了有关这种情况的问题。

I forked a repo of the code above: https://github.com/OriTheElf/TextViewDemo我分叉了上面代码的回购: https : //github.com/OriTheElf/TextViewDemo

The two locations return by the method: recognizer.location(in: notesTextView) is not the same, maybe something happened in the notesTextView or the recognizer.方法返回的两个位置:recognizer.location(in: notesTextView) 不一样,可能是notesTextView或者识别器发生了什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM