如何使用 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
    }
}