iOS AsyncDisplayKit / 纹理的 ASAbsoluteLayoutSpec 不会拉伸内容以填充宽度

问题描述 投票:0回答:1

我在 iOS 应用程序中使用

AsyncDisplayKit/Texture
来显示一个简单的列表。在每一行上,我想水平显示一些文本和图像,并在该行的右下角显示一个三角形。我有以下简单的代码可以演示整个问题:

import UIKit
import SnapKit
import AsyncDisplayKit

class ViewController: UIViewController, ASTableDataSource {

    let tableNode = ASTableNode()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.addSubnode(tableNode)
        tableNode.view.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        tableNode.dataSource = self
    }

    func tableNode(_ tableNode: ASTableNode, numberOfRowsInSection section: Int) -> Int {
        return 100
    }
    
    func tableNode(_ tableNode: ASTableNode, nodeBlockForRowAt indexPath: IndexPath) -> ASCellNodeBlock {
        let row = indexPath.row
        return {
            return MyCellNode(str: "Row \(row)")
        }
    }

}

let sizeToUse = 15.0

class MyCellNode: ASCellNode {
    private var title = ASTextNode()
    private let savedIcon = SaveIconNode()
    private var thumbnailNode = ASNetworkImageNode()
    
    init(str : String) {
        super.init()
        automaticallyManagesSubnodes = true
        automaticallyRelayoutOnSafeAreaChanges = true
        automaticallyRelayoutOnLayoutMarginsChanges = true
        
        title.attributedText = NSAttributedString(string: str, attributes: [.foregroundColor:UIColor.white,.font:UIFont.systemFont(ofSize: 30, weight: .medium)])
        title.backgroundColor = .darkGray
        
        thumbnailNode = ASNetworkImageNode()
        thumbnailNode.isLayerBacked = true
        thumbnailNode.cornerRoundingType = .precomposited
        thumbnailNode.cornerRadius = sizeToUse
        thumbnailNode.style.preferredSize = CGSize(width: 60, height: 60)
        thumbnailNode.url = URL(string: "https://favicon.mars51.com/instagram.com")
    }
    
    override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
        
        
        
        let content = ASStackLayoutSpec(direction: .horizontal, spacing: sizeToUse, justifyContent: .spaceBetween, alignItems: .start, children: [title,thumbnailNode])
        
        
        let inseted = ASInsetLayoutSpec(insets: UIEdgeInsets(top: sizeToUse, left: sizeToUse, bottom: sizeToUse, right: sizeToUse), child: content)
        
        
        savedIcon.style.preferredSize = CGSize(width: sizeToUse, height: sizeToUse)
        savedIcon.style.layoutPosition = CGPoint(x: constrainedSize.max.width - sizeToUse, y: 0)
        
        let finalLayout = ASAbsoluteLayoutSpec(sizing: .default, children: [inseted,savedIcon])
        
        
        return finalLayout
    }
    
    override func layout() {
        super.layout()
        var f = savedIcon.frame
        f.origin.y = calculatedSize.height - f.height
        savedIcon.frame = f
    }
}

class SaveIconNode: ASDisplayNode {
    
    override init() {
        super.init()
        isLayerBacked = true
        backgroundColor = .clear
        isOpaque = false
    }
    
    override class func draw(_ bounds: CGRect, withParameters parameters: Any?, isCancelled isCancelledBlock: () -> Bool, isRasterizing: Bool) {
        
        guard let context = UIGraphicsGetCurrentContext() else { return }

        context.beginPath()
        context.move(to: CGPoint(x: bounds.maxX, y: bounds.minY))
        context.addLine(to: CGPoint(x: bounds.maxX, y: bounds.maxY))
        context.addLine(to: CGPoint(x: bounds.minX, y: bounds.maxY))
        context.closePath()

        UIColor.green.setFill()
        context.fillPath()
    }
}

渲染如下:

如您所见,行中的内容并未拉伸行的整个宽度。这似乎是由

ASAbsoluteLayoutSpec
引起的。我不确定为什么会发生以及如何解决它。请注意,我已在
sizing: .default
上指定了
ASAbsoluteLayoutSpec
,并且文档指出:

https://texturegroup.org/docs/layout2-layoutspec-types.html

sizing:确定绝对规格将占用多少空间。选项包括:默认和适合的大小。

在源代码中,它说

default
The spec will take up the maximum size possible.
:

/** How much space the spec will take up. */
typedef NS_ENUM(NSInteger, ASAbsoluteLayoutSpecSizing) {
  /** The spec will take up the maximum size possible. */
  ASAbsoluteLayoutSpecSizingDefault,
  /** Computes a size for the spec that is the union of all children's frames. */
  ASAbsoluteLayoutSpecSizingSizeToFit,
};

所以我认为我的代码是正确的。

如果我不包含

ASAbsoluteLayoutSpec
而只是包含
return inseted
,那么看起来还不错:

但是我无法包含我的

savedIcon
三角形。

我尝试在所有节点上设置

.style.flexGrow = 1
.style.alignSelf = .stretch
,但这没有任何区别。

ios swift objective-c flexbox asyncdisplaykit
1个回答
0
投票

我以不同的方式找到了解决方案。

  1. 我去掉了

    func layout()
    功能。

  2. 我将

    savedIcon
    放入
    ASInsetLayoutSpec
    中,其
    top
    left
    设置为
    CGFloat.infinity

  3. 我返回了一个

    ASOverlayLayoutSpec
    ,其子级是
    inseted
    内容,覆盖层是上面创建的
    savedIconSpec

我从下面的

Photo with Inset Text Overlay
示例中了解到了这个技巧:

https://texturegroup.org/docs/automatic-layout-examples-2.html

现在我的

layoutSpecThatFits
看起来像这样:

override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
        
    let content = ASStackLayoutSpec(direction: .horizontal, spacing: sizeToUse, justifyContent: .spaceBetween, alignItems: .start, children: [title,thumbnailNode])
    
    let inseted = ASInsetLayoutSpec(insets: UIEdgeInsets(top: sizeToUse, left: sizeToUse, bottom: sizeToUse, right: sizeToUse), child: content)
    
    savedIcon.style.preferredSize = CGSize(width: sizeToUse, height: sizeToUse)
    savedIcon.style.layoutPosition = CGPoint(x: constrainedSize.max.width - sizeToUse, y: 0)
    
    let savedIconSpec = ASInsetLayoutSpec(insets: UIEdgeInsets(top: CGFloat.infinity, left: CGFloat.infinity, bottom: 0, right: 0), child: savedIcon)
    
    return ASOverlayLayoutSpec(child: inseted, overlay: savedIconSpec)
}
© www.soinside.com 2019 - 2024. All rights reserved.