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

点击UITextView指定位置获取对应行文本并修改其颜色

Fix: Get Tapped Line Text & Update Its Color in UITextView

Hey there! You're already doing great by figuring out how to get the tapped line number. Let's build on that to grab the line's text and change its color—here's a step-by-step solution:

Step 1: Update Your Tap Handler to Get the Line's Text Range

Instead of relying solely on font.lineHeight to calculate the line content, use UITextView's layoutManager (it's designed to handle text layout accurately, even with mixed fonts or line heights). Here's the revised code:

func handleTapped(sender: UITapGestureRecognizer) {
    print("tapped")
    guard sender.state == .recognized else { return }
    
    let location = sender.location(ofTouch: 0, in: TextView)
    print(location)
    
    // Guard against invalid taps and missing required components
    guard location.y >= 0, 
          location.y <= TextView.contentSize.height,
          let layoutManager = TextView.layoutManager,
          let textStorage = TextView.textStorage else {
        return
    }
    
    // Calculate the glyph index at the tapped location
    let glyphIndex = layoutManager.glyphIndex(for: location, in: TextView.textContainer, fractionOfDistanceThroughGlyph: nil)
    
    // Get the full range of the line containing this glyph
    let lineGlyphRange = layoutManager.lineRange(forGlyphAt: glyphIndex)
    
    // Convert glyph range to character range (matches the actual text in the string)
    guard let lineCharRange = layoutManager.characterRange(forGlyphRange: lineGlyphRange, actualGlyphRange: nil) else {
        return
    }
    
    // Extract the text of the tapped line
    let lineText = (TextView.text as NSString).substring(with: lineCharRange)
    print("Tapped line number: \(Int(layoutManager.lineNumber(forGlyphAt: glyphIndex, effectiveRange: nil)) + 1)") // Adjust to 1-based if needed
    print("Tapped line text: \(lineText)")
    
    // Step 2: Update the line's text color
    let mutableAttributedText = NSMutableAttributedString(attributedString: TextView.attributedText)
    // Replace UIColor.red with your desired color
    mutableAttributedText.addAttribute(NSAttributedString.Key.foregroundColor, 
                                       value: UIColor.red, 
                                       range: lineCharRange)
    TextView.attributedText = mutableAttributedText
}

Key Notes to Keep in Mind

  • Accurate Range Calculation: Using layoutManager ensures you get the correct line range even if your text has varying fonts, line heights, or embedded images—something calculating with font.lineHeight can't handle reliably.
  • 1-Based vs 0-Based Line Numbers: The code above includes a way to get a 1-based line number (adding 1) if you need it for display, but the range calculations use 0-based indices which are standard for string operations.
  • Attributed Text: We use NSMutableAttributedString to modify only the tapped line's color without affecting the rest of the text. If your text already has other attributes (like bold or italics), this preserves them.

Quick Troubleshooting

  • If the color doesn't update: You don't need the text view to be editable to update its attributedText—double-check that the lineCharRange is valid (print it to confirm).
  • If the line number is off: The layoutManager.lineNumber(forGlyphAt:) method returns a 0-based index, so adding 1 gives you the 1-based line number you might expect.

内容的提问来源于stack exchange,提问作者Tarun Mehta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:55:08