Skip to content

Latest commit

 

History

History
410 lines (281 loc) · 13.4 KB

README_CN.md

File metadata and controls

410 lines (281 loc) · 13.4 KB

Logo

AttributedString - 基于Swift插值方式优雅的构建富文本

License  Swift  Platform  Swift Package Manager  Carthage  Cocoapods

特性

  • 使用插值构建富文本 流畅的编码体验 优雅自然的样式设置.
  • 丰富的控件扩展支持.
  • 支持多层富文本嵌套并提供嵌套样式优先级策略.
  • 支持全部NSAttributedString.Key特性.
  • 支持 iOS & macOS & watchOS & tvOS.
  • 支持文本和附件点击或长按事件回调, 支持高亮样式.
  • 支持异步图片附件, 可以将远程图片资源加载到UITextView中.
  • 支持视图附件, 可以将自定义视图通过富文本添加到UITextView中.
  • 更多新特性的不断加入.

截屏

Simple

Coding

All Font
Kern Stroke

安装

CocoaPods - Podfile

pod 'AttributedString'

Carthage - Cartfile

github "lixiang1994/AttributedString"

选择 Xcode 菜单 File > Swift Packages > Add Package Dependency 输入仓库地址.

Repository: https://github.com/lixiang1994/AttributedString

将以下内容添加到你的 Package.swift:

.package(url: "https://github.com/lixiang1994/AttributedString.git", from: "version")

使用

首先导入

import AttributedString

初始化

// 常规初始化
let a: ASAttributedString = .init("lee", .font(.systemFont(ofSize: 13)))
// 插值初始化
let b: ASAttributedString = "\("lee", .font(.systemFont(ofSize: 13)))"

下面是一些简单示例. 支持所有设备和模拟器:

字体:

textView.attributed.text = """

\("fontSize: 13", .font(.systemFont(ofSize: 13)))

\("fontSize: 20", .font(.systemFont(ofSize: 20)))

\("fontSize: 22 weight: semibold", .font(.systemFont(ofSize: 22, weight: .semibold)))

"""

字色:

textView.attributed.text = """

\("foregroundColor", .foreground(.white))

\("foregroundColor", .foreground(.red))

"""

删除线:

textView.attributed.text = """

\("strikethrough: single", .strikethrough(.single))

\("strikethrough: double color: .red", .strikethrough(.double, color: .red))

"""

附件: (不包括 watchOS)

// ASAttributedString.Attachment

textView.attributed.text = """

\(.data(xxxx, type: "zip"))

\(.file(try!.init(url: .init(fileURLWithPath: "xxxxx"), options: [])))

\(.attachment(NSTextAttachment()))

"""

附件 图片: (不包括 watchOS)

// ASAttributedString.ImageAttachment

textView.attributed.text = """

\(.image(UIImage(named: "xxxx")))

\(.image(UIImage(named: "xxxx"), .custom(size: .init(width: 200, height: 200))))

\(.image(UIImage(named: "xxxx"), .proposed(.center))).

"""

附件 异步图片: (仅支持 iOS: UITextView)

// ASAttributedString.AsyncImageAttachment

textView.attributed.text = """

\(.image(url, placeholder: xxxxx))

"""

自定义加载器 例如使用Kingfisher加载图片, 默认加载器使用的是URLSession:

ASAttributedString.AsyncImageAttachment.Loader = AsyncImageAttachmentKingfisherLoader.self

具体细节请查看Demo中AttachmentViewController.swift文件.

附件 视图: (仅支持 iOS: UITextView)

// ASAttributedString.ViewAttachment

textView.attributed.text = """

\(.view(xxxxView))

\(.view(xxxxView, .custom(size: .init(width: 200, height: 200))))

\(.view(xxxxView, .proposed(.center))).

"""

包装:

let a: ASAttributedString = .init("123", .background(.blue))
let b: ASAttributedString = .init("456", .background(.red))
textView.attributed.text = "\(wrap: a) \(wrap: b, .paragraph(.alignment(.center)))"

// 默认为嵌入模式, 嵌套的内部样式优先于外部样式
textView.attributed.text = "\(wrap: a, .paragraph(.alignment(.center)))"
textView.attributed.text = "\(wrap: .embedding(a), .paragraph(.alignment(.center)))"
// 覆盖模式, 嵌套的外部样式优先于内部样式
textView.attributed.text = "\(wrap: .override(a), .paragraph(.alignment(.center)))"

拼接:

let a: ASAttributedString = .init("123", .background(.blue))
let b: ASAttributedString = .init("456", .background(.red))
let c: ASAttributedString = .init("789", .background(.gray))
textView.attributed.text = a + b
textView.attributed.text += c

检查:

var string: ASAttributedString = .init("我的电话号码是+86 18611401994.", .background(.blue))
string.add(attributes: [.foreground(color)], checkings: [.phoneNumber])
textView.attributed.text = string
var string: ASAttributedString = .init("打开 https://www.apple.com 和 https://github.com/lixiang1994/AttributedString", .background(.blue))
string.add(attributes: [.foreground(color)], checkings: [.link])
textView.attributed.text = string
var string: ASAttributedString = .init("123456789", .background(.blue))
string.add(attributes: [.foreground(color)], checkings: [.regex("[0-6]")])
textView.attributed.text = string

动作: (仅支持 iOS: UILabel / UITextView 和 macOS: NSTextField)

对于复杂的样式, 推荐优先使用 UITextView.

UITextView 需要将 isEditableisSelectable 属性设置为 false.

点击:
// 文本
let a: ASAttributedString = .init("lee", .action({  }))
// 附件 (图片)
let b: ASAttributedString = .init(.image(image), action: {
    // code
})

// 建议使用函数作为参数 语法上比直接使用闭包更加整洁.
func clicked() {
    // code
}
// 正常初始化
let c: ASAttributedString = .init("lee", .action(clicked))
let d: ASAttributedString = .init(.image(image), action: clicked)
// 字面量初始化
let e: ASAttributedString = "\("lee", .action(clicked))"
let f: ASAttributedString = "\(.image(image), action: clicked)"

// 获取更多信息 
func clicked(_ result: ASAttributedString.Action.Result) {
    switch result.content {
    case .string(let value):
        print("点击了文本: \(value) range: \(result.range)")
                
    case .attachment(let value):
        print("点击了附件: \(value) range: \(result.range)")
    }
}

label.attributed.text = "This is \("Label", .font(.systemFont(ofSize: 20)), .action(clicked))"
textView.attributed.text = "This is a picture \(.image(image, .custom(size: .init(width: 100, height: 100))), action: clicked) Displayed in custom size."
按住:
func pressed(_ result: ASAttributedString.Action.Result) {
    switch result.content {
    case .string(let value):
        print("按住了文本: \(value) range: \(result.range)")
                
    case .attachment(let value):
        print("按住了附件: \(value) range: \(result.range)")
    }
}

label.attributed.text = "This is \("Long Press", .font(.systemFont(ofSize: 20)), .action(.press, pressed))"
textView.attributed.text = "This is a picture \(.image(image, .custom(size: .init(width: 100, height: 100))), trigger: .press, action: pressed) Displayed in custom size."
高亮样式:
func clicked(_ result: ASAttributedString.Action.Result) {
    switch result.content {
    case .string(let value):
        print("点击了文本: \(value) range: \(result.range)")
                
    case .attachment(let value):
        print("点击了附件: \(value) range: \(result.range)")
    }
}

label.attributed.text = "This is \("Label", .font(.systemFont(ofSize: 20)), .action([.foreground(.blue)], clicked))"
自定义:
// 触发方式为 按住, 高亮样式为 蓝色背景色和白色文字
let custom = ASAttributedString.Action(.press, highlights: [.background(.blue), .foreground(.white)]) { (result) in
    switch result.content {
    case .string(let value):
        print("按住了文本: \(value) range: \(result.range)")
        
    case .attachment(let value):
        print("按住了附件: \(value) range: \(result.range)")
    }
}

label.attributed.text = "This is \("Custom", .font(.systemFont(ofSize: 20)), .action(custom))"
textView.attributed.text = "This is a picture \(.image(image, .original(.center)), action: custom) Displayed in original size."

监听: (仅支持 iOS: UILabel / UITextView 和 macOS: NSTextField)

// 监听 电话号码类型的点击事件 并设置点击时高亮样式为蓝色字体
label.attributed.observe([.phoneNumber], highlights: [.foreground(.blue)]) { (result) in
    print("当前点击了 \(result)")
}

// 监听 链接和时间类型的点击事件 并设置点击时高亮样式为蓝色字体
textView.attributed.observe([.link, .date], highlights: [.foreground(.blue)]) { (result) in
    print("当前点击了 \(result)")
}

更多示例请查看工程应用.

通过Attribute类提供的属性

以下属性可用:

属性 类型 描述
font UIFont 字体
color UIColor 字色
background UIColor 背景色
paragraph ParagraphStyle 段落样式
ligature Bool 连体字
kern CGFloat 字间距
strikethrough NSUnderlineStyle . UIColor 删除线样式与颜色 (如果颜色为空 则和字色一致)
underline NSUnderlineStyle , UIColor 下划线样式与颜色 (如果颜色为空 则和字色一致)
link String / URL 链接
baselineOffset CGFloat 基准线偏移
shadow NSShadow 阴影
stroke CGFloat, UIColor 描线宽度与颜色
textEffect NSAttributedString.TextEffectStyle 文本效果
obliqueness CGFloat 斜体
expansion CGFloat 拉伸/压缩
writingDirection WritingDirection / [Int] 书写方式
verticalGlyphForm Bool 垂直排版 (当前在iOS上, 它始终是水平的)

通过Attribute.Checking枚举提供的Case

CASE 描述
range(NSRange) 自定义范围
regex(String) 正则表达式
action 动作
date 时间 (基于NSDataDetector)
link 链接 (基于NSDataDetector)
address 地址 (基于NSDataDetector)
phoneNumber 电话 (基于NSDataDetector)
transitInformation 航班 (基于NSDataDetector)

贡献

如果您需要实现特定功能或遇到错误,请打开issue。 如果您自己扩展了AttributedString的功能并希望其他人也使用它,请提交拉取请求。

协议

AttributedString 使用 MIT 协议. 有关更多信息,请参阅LICENSE文件.


欢迎入群交流

QQ