SwiftyText 0.0.3

SwiftyText 0.0.3

测试已测试
语言语言 SwiftSwift
许可证 MIT
发布最后发布2016年1月
SPM支持 SPM

Luke 维护。




英文

目标和特性

  • 链接属性(Link Attribute) 设置后,对应区域的文本便支持点击效果,单击以及长按都有对应的.delegate 方法
  • 手势自定义 Link的手势支持点击(Tap)以及长按(LongPress),手势的触发事件都可以通过.delegate 方法进行处理
  • 增强的Attachment 支持基于View的附件,支持和文本垂直方向的各种对齐方式:靠底对齐,居中对齐,靠顶对齐,根据文本高度进行缩放
  • Text Parser 设置后完成文本模式的识别和文本属性的自动设置,支持自动将识别结果加上 link 属性,比如识别文本中的所有 URL 链接,变成可以点击的
  • 文本异步渲染,提升用户体验
  • 无障碍访问(Accessibility),支持 Voice Over 便于盲人使用

知识点

如果你想通过阅读源码来学习 iOS 相关的编程知识,那么通过本项目你可以学到如下一些知识点:

  • 如何直接通过 TextKit 来渲染界面
  • 如何通过 CAShapeLayer 来实现一些特殊形状的 layer
  • 如何实现自定义的手势识别器(Gesture Recognizer),以及多个手势识别器之间如何协同
  • 如果通过继承 NSTextAttachment 并覆盖 attachmentBoundsForTextContainer 方法来实现 attachment 的自定义的垂直对齐方式
  • 如何自定义界面控件以实现 Voice Over 特性

要求

  • iOS 8.0+
  • XCode 7.1+

集成

使用

基本设置

  • text 设置此属性 会替换掉原先设置的 attributedText 的文本,新文本使用 textColor,font,textAlignment,lineSpacing 这些属性进行样式的设置
  • attributedText 设置此属性会替换原先的 text 文本以及所有的相关样式,但是之后重新设置 textColor,font,textAlignment,lineSpacing,paragraphSpacing,firstLineHeadIndent 这些属性的时候,会将样式重新设置到整个 attributedText
  • numberOfLines 将设置文本控件的最大行数,lineBreakMode 设置文本的断行模式(目前发现一个 Text Kit 的 bug,当 lineBreakMode 设置为 NSLineBreakByCharWrapping 的时候 numberOfLines 起不了约束的作用)

SwiftyText 提供了一些 NSAttributedString 以及 NSMutableAttributedString 的扩展方法,方便使用者快捷设置自己的 Attributed String

extension NSAttributedString {
    public func isValidRange(range: NSRange) -> Bool
    public func entireRange() -> NSRange
    public func proposedSizeWithConstrainedSize(constrainedSize: CGSize, exclusionPaths: [UIBezierPath]?, lineBreakMode: NSLineBreakMode?, maximumNumberOfLines: Int?) -> CGSize //计算最佳Size
    public func neighbourFontDescenderWithRange(range: NSRange) -> CGFloat
}

extension NSMutableAttributedString {
    public var font: UIFont?
    public var foregroundColor: UIColor?
    public func setFont(font: UIFont?, range: NSRange)
    public func setForegroundColor(foregroundColor: UIColor?, range: NSRange)
    public func setLink(link: SwiftyText.SwiftyTextLink?, range: NSRange)
    public func insertAttachment(attachment: SwiftyText.SwiftyTextAttachment, atIndex loc: Int)
}

这里创建一个 SwiftyLabel,代码如下:

let label = SwiftyLabel(frame: CGRectMake(0, 0, 300, 400))
label.center = self.view.center
label.delegate = self
label.backgroundColor = UIColor(red: 243/255.0, green: 1, blue: 236/255.0, alpha: 1)
label.text = "Swift is a powerful and intuitive programming language for iOS, OS X, tvOS, and watchOS.  https://developer.apple.com/swift/resources/ . Writing Swift code is interactive and fun, the syntax is concise yet expressive, and apps run lightning-fast. Swift is ready for your next project — or addition into your current app — because Swift code works side-by-side with Objective-C.  "
label.textContainerInset = UIEdgeInsetsMake(6, 6, 6, 6)
label.font = UIFont.systemFontOfSize(14)
label.textColor = UIColor.blackColor()
label.firstLineHeadIndent = 24
label.drawsTextAsynchronously = true

链接

这里的链接指的是文本中可以点击的内容。链接属性在 SwiftyText 中使用 SwiftyTextLink 来表示,SwiftyTextLink 中包含如下的一些属性

  • attributes 设置链接属性对应的文本的样式,使用标准的 NSAttributedString 的 attributes
  • highlightedAttributes 点击高亮时 对应文本的样式属性,非高亮的时候会恢复到高亮之前的样式
  • highlightedMaskRadius,highlightedMaskColor 分别设置点击时 文本上的蒙层边角半径以及颜色
  • URL,date,timeZone,phoneNumber,addressComponents 这些是可能出现的常见的链接类型的相关值,如果不是这些特定链接,可以使用 userInfo 自己进行设置

代码示例:

let link = SwiftyTextLink()
link.URL = NSURL(string: "https://developer.apple.com/swift/")
link.attributes = [NSForegroundColorAttributeName:UIColor(red: 0, green: 122/255.0, blue: 1.0, alpha: 1.0),NSUnderlineStyleAttributeName:NSUnderlineStyle.StyleSingle.rawValue]
label.setLink(link, range: NSMakeRange(0, 5))

Text Parser

在很多情况下我们需要对特定的模式的文本做特殊处理,诸如文本替换,或者特定的文本设置特定的属性,诸如颜色,字体等,这个时候我们便可以通过实现 SwiftyTextParser 协议来实现自己的 Text Parser,设置到 SwiftyLabel 中。Text Parser 存在的好处在于处理逻辑的复用。在 SwiftyText 中定义了一种叫做 Detector 的特殊 Text Parser,可以通过设置正则以及对应的属性的方式来创建一个 Parser。还有一个特殊的 Text Parser 叫做 SwiftyTextSuperParser,它其实就是一个 parser container,是一个 Text Parser 的容器,这样就可以将多个 Text Parser 合并成一个。

下面主要讲解下 Detector

  • name detector 的名字
  • linkable 是否是链接,如果是链接的话会对匹配的文本设置上 Link 属性,支持点击,你还可以通过 linkGestures 来设置链接支持的手势
  • regularExpression 匹配的模式,类型为 NSRegularExpression 的实例或者其子类的对象
  • attributes 匹配的文本需要设置的属性,比如特定颜色,字体,下划线等
  • highlightedAttributes 当 linkable 为 YES 时,此属性用来决定匹配的文本的点击时的高亮属性
  • replacementBlock 当匹配的文本的属性的设置比较复杂的时候,没法通过简单的 attributes 来实现的时候,可以通过此 block 返回替换的 attributedText
let detector = SwiftyTextDetector.detectorWithType([.URL,.Address])
if detector != nil {
    label.parser = detector
}

附件

SwiftyTextAttachment 在 NSTextAttachment 上做了增强,同时支持基于图片以及基于 UIView 的 Attachment。图片,UIView 类型的附件都支持和文本在纵向上的各种对齐方式:靠顶对齐,居中,靠底对齐,缩放以适配文本高度,都支持通过设置 padding 来控制前后的 padding。图片 Attachment 还支持通过设置 imageSize 来控制图片的大小(当垂直对齐为 靠顶对齐,居中,靠底对齐时起作用)

 let imageAttachment = SwiftyTextAttachment()
 imageAttachment.image = UIImage(named: "logo")
 imageAttachment.attachmentTextVerticalAlignment = .Top
 label.insertAttachment(imageAttachment, atIndex: label.textStorage.length)

 let sliderAttachment = SwiftyTextAttachment()
 let slider = UISlider()
 sliderAttachment.contentView = slider;
 sliderAttachment.padding = 3.0
 sliderAttachment.attachmentTextVerticalAlignment = .Center
 label.insertAttachment(sliderAttachment, atIndex: 8)

下图为 demo 的效果截图:

其余Text Kit的特性

其余的Text Kit的特性,比如exclusionPaths,可以通过SwiftyLabel的exclusionPaths属性进行设置。

许可证

SwiftyText 基于 MIT 许可证开源。具体详情请查看根目录下的LICENSE文件。