点击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
layoutManagerensures you get the correct line range even if your text has varying fonts, line heights, or embedded images—something calculating withfont.lineHeightcan'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
NSMutableAttributedStringto 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 thelineCharRangeis 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
相关产品推荐
相关产品推荐

