You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UITextView滚动后无法准确获取点击单词的问题求助

解决UITextView滚动后点击获取单词不准确的问题

你遇到的核心问题是手动调整点击坐标的方式不符合UITextView文本布局的逻辑——你直接把contentOffsetY加到点击坐标上,但这种方式没有考虑文本容器的内边距、文本排版的行高差异等细节,滚动后自然无法精准匹配到点击的单词。

下面是修正后的完整解决方案:

步骤1:移除错误的坐标调整逻辑,改用LayoutManager计算准确位置

UITextView的layoutManager已经封装了文本坐标的计算逻辑,我们可以直接用它来获取点击位置对应的文本索引,无需手动调整偏移量。

步骤2:修正点击手势处理代码

替换你原来的handleTap和word(atPosition:)方法为以下代码:

@objc func handleTap(_ sender: UITapGestureRecognizer) {
    notesTextView.isEditable = true
    notesTextView.textColor = UIColor.white
    
    guard let textView = sender.view as? UITextView else { return }
    let tapPoint = sender.location(in: textView)
    
    // 通过LayoutManager获取点击位置对应的Glyph索引
    let glyphIndex = textView.layoutManager.glyphIndex(for: tapPoint, in: textView.textContainer, fractionOfDistanceThroughGlyph: nil)
    
    // 将Glyph索引转换为UITextPosition
    guard let tapPosition = textView.position(from: textView.beginningOfDocument, offset: glyphIndex) else { return }
    
    // 获取点击位置所在的单词范围
    if let wordRange = textView.tokenizer.rangeEnclosingPosition(tapPosition, with: .word, inDirection: UITextDirection(rawValue: 1)) {
        if let tappedWord = textView.text(in: wordRange) {
            print("Word: \(tappedWord)")
            // 这里可以添加你对选中单词的后续处理逻辑
        }
    }
}

关键说明

  • layoutManager.glyphIndex(for:in:fractionOfDistanceThroughGlyph:):会自动处理滚动偏移、文本容器内边距、文本排版等因素,返回点击位置对应的字形(Glyph)索引,这是匹配文本位置的准确方式。
  • 确保你的UITextView初始状态下isSelectable属性为true(即使isEditable为false)——因为tokenizer需要文本可选才能正常解析单词范围,你可以在初始化时设置:
    notesTextView.isSelectable = true
    notesTextView.isEditable = false
    

这样修改后,无论UITextView是否滚动,都能精准获取到点击的单词啦!

内容的提问来源于stack exchange,提问作者Amrit Sidhu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:35:57