如何使用 Texture 在 ASCellNode 中正确添加节点
How can I properly add nodes in an ASCellNode using Texture
我正在学习AsyncDisplayKit/Texture。我正在尝试使用自定义单元格创建 ASTableNode
。
我正在努力了解如何正确设置和锚定我在 ExampleNode
中创建的节点。
我试过了
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
let stack = ASStackLayoutSpec.vertical()
stack.children = textNode
return stack
}
但是有错误
Cannot assign value of type 'ASTextNode' to type '[ASLayoutElement]?'
然后我将 layoutSpecThatFits
更新为
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
return ASStackLayoutSpec(
direction: .horizontal,
spacing: 16,
justifyContent: .start,
alignItems: .center,
children: [textNode]
)
}
但是这会使文本与单元格的左侧发生碰撞。根本没有应用间距。
我正在努力寻找使用它的体面指南,所以如果答案显而易见,请原谅我。
使用以下 class 向单元格添加节点的正确方法是什么?
import AsyncDisplayKit
final class FeedNodeController: ASViewController<ASDisplayNode> {
var tableNode: ASTableNode {
return node as! ASTableNode
}
private lazy var tableNodeProvider = FeedTableNodeProvider()
init() {
super.init(node: ASTableNode())
tableNode.delegate = tableNodeProvider
tableNode.dataSource = tableNodeProvider
tableNode.view.tableFooterView = UIView()
}
required init?(coder aDecoder: NSCoder) {
return nil
}
}
class FeedTableNodeProvider: NSObject {
private let feed = ["Foo", "Bar", "Boo", "Baz"]
}
extension FeedTableNodeProvider: ASTableDataSource, ASTableDelegate {
func numberOfSections(in tableNode: ASTableNode) -> Int {
return 1
}
func tableNode(_ tableNode: ASTableNode, nodeBlockForRowAt indexPath: IndexPath) -> ASCellNodeBlock {
let node = { [unowned self] () -> ASCellNode in
return ExampleNode(text: self.feed[indexPath.row])
}
return node
}
func tableNode(_ tableNode: ASTableNode, numberOfRowsInSection section: Int) -> Int {
return feed.count
}
}
class ExampleNode: ASCellNode {
private lazy var textNode: ASTextNode = {
let node = ASTextNode()
node.backgroundColor = .blue
return node
}()
init(text: String) {
super.init()
textNode.attributedText = NSAttributedString(string: text)
backgroundColor = .purple
addSubnode(textNode)
}
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
return ASStackLayoutSpec(
direction: .horizontal,
spacing: 16,
justifyContent: .start,
alignItems: .center,
children: [textNode]
)
}
}
ASTexNode
将根据文本的长度计算其 width
如果您未为其设置任何宽度
不太明白你问的是什么
如果你想添加一个 padding
,你可以用 ASInsetLayoutSpec
包装你当前的 ASStackLayoutSpec
...
let mainStack = ASStackLayoutSpec(
direction: .horizontal,
spacing: 16,
justifyContent: .start,
alignItems: .center,
children: [textNode])
let paddedMainStack = ASInsetLayoutSpec(insets: UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16), child: mainStack)
return paddedMainStack
...
那么您将拥有您的 padding
快乐纹理
看看ASDKgram-Swift example in the texture repo, PhotoTableNodeCell。
import Foundation
import AsyncDisplayKit
class PhotoTableNodeCell: ASCellNode {
// MARK: Properties
let usernameLabel = ASTextNode()
let timeIntervalLabel = ASTextNode()
let photoLikesLabel = ASTextNode()
let photoDescriptionLabel = ASTextNode()
let avatarImageNode: ASNetworkImageNode = {
let node = ASNetworkImageNode()
node.contentMode = .scaleAspectFill
// Set the imageModificationBlock for a rounded avatar
node.imageModificationBlock = ASImageNodeRoundBorderModificationBlock(0, nil)
return node
}()
let photoImageNode: ASNetworkImageNode = {
let node = ASNetworkImageNode()
node.contentMode = .scaleAspectFill
return node
}()
// MARK: Lifecycle
init(photoModel: PhotoModel) {
super.init()
automaticallyManagesSubnodes = true
photoImageNode.url = URL(string: photoModel.url)
avatarImageNode.url = URL(string: photoModel.user.profileImage)
usernameLabel.attributedText = photoModel.attributedStringForUserName(withSize: Constants.CellLayout.FontSize)
timeIntervalLabel.attributedText = photoModel.attributedStringForTimeSinceString(withSize: Constants.CellLayout.FontSize)
photoLikesLabel.attributedText = photoModel.attributedStringLikes(withSize: Constants.CellLayout.FontSize)
photoDescriptionLabel.attributedText = photoModel.attributedStringForDescription(withSize: Constants.CellLayout.FontSize)
}
// MARK: ASDisplayNode
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
// Header Stack
var headerChildren: [ASLayoutElement] = []
let headerStack = ASStackLayoutSpec.horizontal()
headerStack.alignItems = .center
avatarImageNode.style.preferredSize = CGSize(
width: Constants.CellLayout.UserImageHeight,
height: Constants.CellLayout.UserImageHeight
)
headerChildren.append(ASInsetLayoutSpec(insets: Constants.CellLayout.InsetForAvatar, child: avatarImageNode))
usernameLabel.style.flexShrink = 1.0
headerChildren.append(usernameLabel)
let spacer = ASLayoutSpec()
spacer.style.flexGrow = 1.0
headerChildren.append(spacer)
timeIntervalLabel.style.spacingBefore = Constants.CellLayout.HorizontalBuffer
headerChildren.append(timeIntervalLabel)
let footerStack = ASStackLayoutSpec.vertical()
footerStack.spacing = Constants.CellLayout.VerticalBuffer
footerStack.children = [photoLikesLabel, photoDescriptionLabel]
headerStack.children = headerChildren
let verticalStack = ASStackLayoutSpec.vertical()
verticalStack.children = [
ASInsetLayoutSpec(insets: Constants.CellLayout.InsetForHeader, child: headerStack),
ASRatioLayoutSpec(ratio: 1.0, child: photoImageNode),
ASInsetLayoutSpec(insets: Constants.CellLayout.InsetForFooter, child: footerStack)
]
return verticalStack
}
}
我正在学习AsyncDisplayKit/Texture。我正在尝试使用自定义单元格创建 ASTableNode
。
我正在努力了解如何正确设置和锚定我在 ExampleNode
中创建的节点。
我试过了
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
let stack = ASStackLayoutSpec.vertical()
stack.children = textNode
return stack
}
但是有错误
Cannot assign value of type 'ASTextNode' to type '[ASLayoutElement]?'
然后我将 layoutSpecThatFits
更新为
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
return ASStackLayoutSpec(
direction: .horizontal,
spacing: 16,
justifyContent: .start,
alignItems: .center,
children: [textNode]
)
}
但是这会使文本与单元格的左侧发生碰撞。根本没有应用间距。
我正在努力寻找使用它的体面指南,所以如果答案显而易见,请原谅我。
使用以下 class 向单元格添加节点的正确方法是什么?
import AsyncDisplayKit
final class FeedNodeController: ASViewController<ASDisplayNode> {
var tableNode: ASTableNode {
return node as! ASTableNode
}
private lazy var tableNodeProvider = FeedTableNodeProvider()
init() {
super.init(node: ASTableNode())
tableNode.delegate = tableNodeProvider
tableNode.dataSource = tableNodeProvider
tableNode.view.tableFooterView = UIView()
}
required init?(coder aDecoder: NSCoder) {
return nil
}
}
class FeedTableNodeProvider: NSObject {
private let feed = ["Foo", "Bar", "Boo", "Baz"]
}
extension FeedTableNodeProvider: ASTableDataSource, ASTableDelegate {
func numberOfSections(in tableNode: ASTableNode) -> Int {
return 1
}
func tableNode(_ tableNode: ASTableNode, nodeBlockForRowAt indexPath: IndexPath) -> ASCellNodeBlock {
let node = { [unowned self] () -> ASCellNode in
return ExampleNode(text: self.feed[indexPath.row])
}
return node
}
func tableNode(_ tableNode: ASTableNode, numberOfRowsInSection section: Int) -> Int {
return feed.count
}
}
class ExampleNode: ASCellNode {
private lazy var textNode: ASTextNode = {
let node = ASTextNode()
node.backgroundColor = .blue
return node
}()
init(text: String) {
super.init()
textNode.attributedText = NSAttributedString(string: text)
backgroundColor = .purple
addSubnode(textNode)
}
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
return ASStackLayoutSpec(
direction: .horizontal,
spacing: 16,
justifyContent: .start,
alignItems: .center,
children: [textNode]
)
}
}
ASTexNode
将根据文本的长度计算其 width
如果您未为其设置任何宽度
不太明白你问的是什么
如果你想添加一个 padding
,你可以用 ASInsetLayoutSpec
ASStackLayoutSpec
...
let mainStack = ASStackLayoutSpec(
direction: .horizontal,
spacing: 16,
justifyContent: .start,
alignItems: .center,
children: [textNode])
let paddedMainStack = ASInsetLayoutSpec(insets: UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16), child: mainStack)
return paddedMainStack
...
那么您将拥有您的 padding
快乐纹理
看看ASDKgram-Swift example in the texture repo, PhotoTableNodeCell。
import Foundation
import AsyncDisplayKit
class PhotoTableNodeCell: ASCellNode {
// MARK: Properties
let usernameLabel = ASTextNode()
let timeIntervalLabel = ASTextNode()
let photoLikesLabel = ASTextNode()
let photoDescriptionLabel = ASTextNode()
let avatarImageNode: ASNetworkImageNode = {
let node = ASNetworkImageNode()
node.contentMode = .scaleAspectFill
// Set the imageModificationBlock for a rounded avatar
node.imageModificationBlock = ASImageNodeRoundBorderModificationBlock(0, nil)
return node
}()
let photoImageNode: ASNetworkImageNode = {
let node = ASNetworkImageNode()
node.contentMode = .scaleAspectFill
return node
}()
// MARK: Lifecycle
init(photoModel: PhotoModel) {
super.init()
automaticallyManagesSubnodes = true
photoImageNode.url = URL(string: photoModel.url)
avatarImageNode.url = URL(string: photoModel.user.profileImage)
usernameLabel.attributedText = photoModel.attributedStringForUserName(withSize: Constants.CellLayout.FontSize)
timeIntervalLabel.attributedText = photoModel.attributedStringForTimeSinceString(withSize: Constants.CellLayout.FontSize)
photoLikesLabel.attributedText = photoModel.attributedStringLikes(withSize: Constants.CellLayout.FontSize)
photoDescriptionLabel.attributedText = photoModel.attributedStringForDescription(withSize: Constants.CellLayout.FontSize)
}
// MARK: ASDisplayNode
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
// Header Stack
var headerChildren: [ASLayoutElement] = []
let headerStack = ASStackLayoutSpec.horizontal()
headerStack.alignItems = .center
avatarImageNode.style.preferredSize = CGSize(
width: Constants.CellLayout.UserImageHeight,
height: Constants.CellLayout.UserImageHeight
)
headerChildren.append(ASInsetLayoutSpec(insets: Constants.CellLayout.InsetForAvatar, child: avatarImageNode))
usernameLabel.style.flexShrink = 1.0
headerChildren.append(usernameLabel)
let spacer = ASLayoutSpec()
spacer.style.flexGrow = 1.0
headerChildren.append(spacer)
timeIntervalLabel.style.spacingBefore = Constants.CellLayout.HorizontalBuffer
headerChildren.append(timeIntervalLabel)
let footerStack = ASStackLayoutSpec.vertical()
footerStack.spacing = Constants.CellLayout.VerticalBuffer
footerStack.children = [photoLikesLabel, photoDescriptionLabel]
headerStack.children = headerChildren
let verticalStack = ASStackLayoutSpec.vertical()
verticalStack.children = [
ASInsetLayoutSpec(insets: Constants.CellLayout.InsetForHeader, child: headerStack),
ASRatioLayoutSpec(ratio: 1.0, child: photoImageNode),
ASInsetLayoutSpec(insets: Constants.CellLayout.InsetForFooter, child: footerStack)
]
return verticalStack
}
}