给 iOS 文本添加个性波浪线:TextWavyLine 库详解

50 阅读2分钟

在移动应用开发中,我们经常需要为文本添加特殊标记效果以突出重要内容。下划线是最常用的方式之一,但传统的直线下划线显得单调乏味。于是,我开发了一个实用的 iOS 开源库 ——TextWavyLine,它能帮助开发者轻松实现文本波浪线下划线效果。

效果

image.png

核心特性

TextWavyLine 的主要优势体现在以下几个方面:

  • 高度自定义:支持自定义波浪线颜色、宽度和波形参数
  • 精准控制:可以为指定文本范围添加波浪线
  • 性能优异:基于 NSLayoutManager 实现,渲染效率高
  • 易于集成:简单几步即可在现有项目中使用

技术实现原理

TextWavyLine 的核心是自定义的WavyLayoutManager类,它继承自NSLayoutManager,通过重写文本绘制逻辑来实现波浪线效果:

  1. 首先在drawGlyphs(forGlyphRange:at:)方法中完成文本的正常绘制
  2. 然后调用自定义的drawWavyUnderlines(forGlyphRange:at:)方法绘制波浪线
  3. 使用 Core Graphics API 绘制正弦曲线作为波浪线
  4. 通过维护波浪线范围数组实现精准的范围控制

快速集成指南

使用步骤

  1. 创建核心组件
let layoutManager = WavyLayoutManager()
let textStorage = NSTextStorage()
let textContainer = NSTextContainer()

textStorage.addLayoutManager(layoutManager)
layoutManager.addTextContainer(textContainer)

2. 创建并配置 UITextView

let textView = UITextView(frame: .zero, textContainer: textContainer)
textView.translatesAutoresizingMaskIntoConstraints = false
textView.font = UIFont.systemFont(ofSize: 18)
// 根据需要设置其他属性

3. 添加波浪线效果

// 为指定范围添加波浪线
layoutManager.addWavyRange(NSRange(location: 5, length: 10))

// 自定义波浪线样式
layoutManager.wavyLineColor = .blue
layoutManager.wavyLineWidth = 1.5
layoutManager.waveHeight = 2.5
layoutManager.waveWidth = 8.0

实际应用场景

TextWavyLine 适用于多种场景:

  • 拼写检查标记(类似系统的拼写错误提示)
  • 重点内容高亮
  • 自定义链接样式
  • 特殊注释或标记
  • 聊天应用中的特殊消息标记

在示例代码中,展示了如何为文本中的特定关键词自动添加波浪线:

private func addWavyLinesToKeywords(text: String, layoutManager: WavyLayoutManager) {
    let nsText = text as NSString
    let keywords = ["波浪线"]
    
    for keyword in keywords {
        var searchRange = NSRange(location: 0, length: nsText.length)
        
        while searchRange.location < nsText.length {
            let foundRange = nsText.range(of: keyword, options: [], range: searchRange)
            if foundRange.location != NSNotFound {
                layoutManager.addWavyRange(foundRange)
                searchRange.location = foundRange.location + foundRange.length
                searchRange.length = nsText.length - searchRange.location
            } else {
                break
            }
        }
    }
}

总结

项目源码已开源在 GitHub,欢迎大家 Star、Fork :

👉 github.com/linghugoogl…