I have a ASViewController
that renders an ASTableNode
.
I'd like to use an ASNetworkImageNode
in each row to render an image.
I know the width / height so am able to set the ratio correctly. As such I am using ASRatioLayoutSpec
on the image.
The issue I am having is, I will be including the ASNetworkImageNode
and other child nodes in my row.
How can I set the ratio correctly in my layoutSpecThatFits
method?
If I change it as follows:
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
let ratio: CGFloat = props.size.height / props.size.width
let imageRatioSpec = ASRatioLayoutSpec(ratio: ratio, child: self.imageNode)
return imageRatioSpec
}
It works perfect, however I can't return any other child nodes this way.
I was expecting something like:
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
let ratio: CGFloat = props.size.height / props.size.width
let imageRatioSpec = ASRatioLayoutSpec(ratio: ratio, child: self.imageNode)
return ASStackLayoutSpec(
direction: .horizontal,
spacing: 16,
justifyContent: .start,
alignItems: .center,
children: [imageRatioSpec, textNode] // returns image and text
)
}
But doesn't show the image, or at the very least does not set a ratio so the image is not visible.
import AsyncDisplayKit
class FeedNodeController: ASViewController<ASTableNode> {
var data = [
FeedItem(url: "https://pbs.twimg.com/media/EAtM2HyXUAEXJkA.jpg", size: .init(width: 1200, height: 800)),
FeedItem(url: "https://pbs.twimg.com/media/EAtBZzOXUAEqeNJ.jpg", size: .init(width: 680, height: 510)),
FeedItem(url: "https://pbs.twimg.com/media/EAsxYhlXoAArJe7.jpg", size: .init(width: 680, height: 453)),
FeedItem(url: "https://pbs.twimg.com/media/EAss0ACXoAAUtlc.jpg", size: .init(width: 1115, height: 1200))
]
init() {
super.init(node: FeedTableNode())
}
required init?(coder aDecoder: NSCoder) {
return nil
}
override func viewDidLoad() {
super.viewDidLoad()
node.dataSource = self
node.delegate = self
node.view.tableFooterView = UIView()
}
}
extension FeedNodeController: ASTableDataSource, ASTableDelegate {
func numberOfSections(in tableNode: ASTableNode) -> Int {
return 1
}
func tableNode(_ tableNode: ASTableNode, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func tableNode(_ tableNode: ASTableNode, nodeBlockForRowAt indexPath: IndexPath) -> ASCellNodeBlock {
let props = data[indexPath.row]
let nodeBlock: ASCellNodeBlock = { () -> ASCellNode in
return FeedCellNode(props)
}
return nodeBlock
}
}
class FeedTableNode: ASTableNode { }
class FeedCellNode: ASCellNode {
private var props: FeedItem
private lazy var imageNode: ASNetworkImageNode = {
let node = ASNetworkImageNode()
return node
}()
init(_ props: FeedItem) {
self.props = props
super.init()
automaticallyManagesSubnodes = true
imageNode.url = props.url
addSubnode(imageNode)
}
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
let ratio: CGFloat = props.size.height / props.size.width
let imageRatioSpec = ASRatioLayoutSpec(ratio: ratio, child: self.imageNode)
return ASStackLayoutSpec(
direction: .horizontal,
spacing: 16,
justifyContent: .start,
alignItems: .center,
children: [imageRatioSpec]
)
}
}
struct FeedItem {
var url: URL
var size: CGSize
init(url: String, size: CGSize) {
self.url = URL(string: url)!
self.size = size
}
}
You need to change your ASStackLayoutSpec
to be a vertical stack.
return ASStackLayoutSpec(
direction: .vertical,
spacing: 16,
justifyContent: .start,
alignItems: .center,
children: [imageRatioSpec, textNode]
)