Telegram 使用的核心 Node

image.png
- 帶箭頭的邊框:右邊的 Node 是左邊 Node 的子類;
- 無箭頭的邊框:相同級別,且與最左側(cè) Node 繼承同一個父類;
1、 --- Text ---
TextNode、ImmediateTextNode 和 ASTextNode 負責(zé)文本渲染。
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 被用來異步調(diào)用布局計算并緩存計算結(jié)果,該方法是被設(shè)計來供上一級調(diào)用的,不然,它將不會呈現(xiàn)任何內(nèi)容,因為緩存的布局為 nil ;
支持 RTL(維語,阿拉伯語等從右到左顯示) 和 Accessibility(視障服務(wù)功能); -
ImmediateTextNode通過聲明更多屬性來控制文本布局樣式使得TextNode更加豐富,它還支持高亮顯示和點擊事件。 -
ASTextNode只需設(shè)置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 圖片和標(biāo)題組成 ,共有四個狀態(tài):normal、 highlighted、selected、disabled。
- HighlightableButtonNode 在點擊按鈕時添加高亮動畫。
4、 --- Status ---
-
ActivityIndicator 仿照
UIActivityIndicatorView樣式并提供靈活的選項來自定義細節(jié),例如顏色、直徑和線寬。
5、 --- Media ---
Telegram 使用了很多組件來支持不同的媒體類型,這里僅僅簡單說明;
-
MediaPlayNode 是 MediaPlayer 的子類,用于在
AVSampleBufferDisplayLayer上渲染視頻幀。 -
WebEmbedPlayerNode 通過
WKWebView播放嵌入網(wǎng)頁的視頻;它支持來自Youtube、Vimeo、Twitch等的視頻。 -
AnimatedStickerNode 用于播放來自
AnimatedStickerNodeSource的動畫。
6、 --- Bar ---
- SearchBarNode、NavigationBar、TabBarNode 和 ToolbarNode 仿照了原生 UIKit 中對應(yīng)的功能;它還消除了不同系統(tǒng)版本之間存在的差異性。
- StatusBar 會在系統(tǒng)狀態(tài)欄顯示通話中的通知文本。