Telegram 使用的核心 Node
- 带箭头的边框:右边的 Node 是左边 Node 的子类;
- 无箭头的边框:相同级别,且与最左侧 Node 继承同一个父类;
1、 --- Text ---
TextNode、ImmediateTextNode 和 ASTextNode 负责文本渲染。
public class TextNode: ASDisplayNode {
public internal(set) var cachedLayout: TextNodeLayout?
public static func asyncLayout(_ maybeNode: TextNode?) -> (TextNodeLayoutArguments) -> (TextNodeLayout, () -> TextNode)
}
public class ImmediateTextNode: TextNode {
public var attributedText: NSAttributedString?
public var textAlignment: NSTextAlignment = .natural
public var truncationType: CTLineTruncationType = .end
public var maximumNumberOfLines: Int = 1
public var lineSpacing: CGFloat = 0.0
public var insets: UIEdgeInsets = UIEdgeInsets()
public var textShadowColor: UIColor?
public var textStroke: (UIColor, CGFloat)?
public var cutout: TextNodeCutout?
public var truncationMode: NSLineBreakMode
public var linkHighlightColor: UIColor?
public var trailingLineWidth: CGFloat?
public var highlightAttributeAction: (([NSAttributedString.Key: Any]) -> NSAttributedString.Key?)?
public var tapAttributeAction: (([NSAttributedString.Key: Any], Int) -> Void)?
public var longTapAttributeAction: (([NSAttributedString.Key: Any], Int) -> Void)?
...
}
public class ASTextNode: ImmediateTextNode {
override public var attributedText: NSAttributedString? {
didSet {
self.setNeedsLayout()
}
}
...
}
-
TextNode
利用CoreText
渲染NSAttributedString
;
它有一个基于row
计算出文本布局的方法 calculateLayout ,并重写父类方法 draw 来渲染文本;
公开方法 asyncLayout 被用来异步调用布局计算并缓存计算结果,该方法是被设计来供上一级调用的,不然,它将不会呈现任何内容,因为缓存的布局为 nil ;
支持 RTL(维语,阿拉伯语等从右到左显示) 和 Accessibility(视障服务功能); -
ImmediateTextNode
通过声明更多属性来控制文本布局样式使得TextNode
更加丰富,它还支持高亮显示和点击事件。 -
ASTextNode
只需设置attributedText
属性就能更新布局,虽然和 AsyncDisplayKit 里的 node 名字一样但并不是同一个。 -
EditableTextNode 扩展
ASEditableTextNode
用来检测 RTL 输入。
2、 --- Image ---
open class ASImageNode: ASDisplayNode {
public var image: UIImage?
}
public class ImageNode: ASDisplayNode {
public func setSignal(_ signal: Signal<UIImage?, NoError>)
}
open class TransformImageNode: ASDisplayNode {
public var imageUpdated: ((UIImage?) -> Void)?
public var contentAnimations: TransformImageNodeContentAnimations = []
public func setSignal(_ signal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>, attemptSynchronously: Bool = false, dispatchOnDisplayLink: Bool = true)
public func setOverlayColor(_ color: UIColor?, animated: Bool)
}
-
ASImageNode 渲染
UIImage
并使用图片的 Size 作为自己的 Size;同样,它和 AsyncDisplayKit 里的 Node 并不是同一个。 -
ImageNode 接收一个
Signal
来异步显示图片;仅在 AvatarNode 使用。 - TransformImageNode 是异步加载图片使用最多的类;它支持在更改图片时使用 alpha 动画,并支持颜色叠加。
3、 --- Button ---
open class ASButtonNode: ASControlNode {
public let titleNode: ImmediateTextNode
public let highlightedTitleNode: ImmediateTextNode
public let disabledTitleNode: ImmediateTextNode
public let imageNode: ASImageNode
public let highlightedImageNode: ASImageNode
public let selectedImageNode: ASImageNode
public let highlightedSelectedImageNode: ASImageNode
public let disabledImageNode: ASImageNode
public let backgroundImageNode: ASImageNode
public let highlightedBackgroundImageNode: ASImageNode
}
open class HighlightTrackingButtonNode: ASButtonNode {
public var highligthedChanged: (Bool) -> Void = { _ in }
}
open class HighlightableButtonNode: HighlightTrackingButtonNode {
...
}
- ASButtonNode 图片和标题组成 ,共有四个状态:normal、 highlighted、selected、disabled。
- HighlightableButtonNode 在点击按钮时添加高亮动画。
4、 --- Status ---
-
ActivityIndicator 仿照
UIActivityIndicatorView
样式并提供灵活的选项来自定义细节,例如颜色、直径和线宽。
5、 --- Media ---
Telegram 使用了很多组件来支持不同的媒体类型,这里仅仅简单说明;
-
MediaPlayNode 是 MediaPlayer 的子类,用于在
AVSampleBufferDisplayLayer
上渲染视频帧。 -
WebEmbedPlayerNode 通过
WKWebView
播放嵌入网页的视频;它支持来自Youtube、Vimeo、Twitch等的视频。 -
AnimatedStickerNode 用于播放来自
AnimatedStickerNodeSource
的动画。
6、 --- Bar ---
- SearchBarNode、NavigationBar、TabBarNode 和 ToolbarNode 仿照了原生 UIKit 中对应的功能;它还消除了不同系统版本之间存在的差异性。
- StatusBar 会在系统状态栏显示通话中的通知文本。