Swift Readjust / Resize layout (ASDisplayNode) on show hide of children node
Posted
技术标签:
【中文标题】Swift Readjust / Resize layout (ASDisplayNode) on show hide of children node【英文标题】:Swift Readjust / Resize layout (ASDisplayNode) on show hide of the children node 【发布时间】:2019-07-12 09:54:02 【问题描述】:我是 AsyncDisplayKit 的新手。所以,我创建了一个新的应用程序来学习基于我真实项目代码的 AsyncDisplayKit animationTransition。 显示/隐藏动画效果完美,但我不知道为什么父节点(ASDisplayNode)在孩子隐藏时没有重新调整布局(对不起,如果我的英语不好)
我已经尝试将 setNeedsLayout() 放在 transitionLayout 测量完成上,但没有任何改变
import AsyncDisplayKit
class HomeView: ASDisplayNode
let topWrapperNode: TopWrapperNode
let loginButtonNode: LoginButtonNode
override required init()
self.topWrapperNode = TopWrapperNode()
self.loginButtonNode = LoginButtonNode()
super.init()
self.automaticallyManagesSubnodes = true
self.automaticallyRelayoutOnSafeAreaChanges = true
self.insetsLayoutMarginsFromSafeArea = true
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec
let verticalStackSpec = ASStackLayoutSpec.vertical()
verticalStackSpec.children = [
self.topWrapperNode,
self.loginButtonNode
]
verticalStackSpec.alignItems = .stretch
verticalStackSpec.justifyContent = .spaceBetween
let displayInset = ASInsetLayoutSpec(
insets: UIEdgeInsets(top: 0, left: 32, bottom: 16, right: 32),
child: verticalStackSpec
)
return ASInsetLayoutSpec(insets: safeAreaInsets, child: displayInset)
func keyboardShowUpdateLayout(keyboardHeight: CGFloat)
// self.topWrapperNode.hideWelcomeLabelNode()
func keyboardHideUpdateLayout()
// self.topWrapperNode.showWelcomeLabelNode()
// MARK - TopWrapperNode
class TopWrapperNode: ASDisplayNode
let welcomeLabelNode: WelcomeLabelNode
// let textFieldNode: TextFieldNode
override required init()
welcomeLabelNode = WelcomeLabelNode()
// textFieldNode = TextFieldNode()
super.init()
self.automaticallyManagesSubnodes = true
self.autoresizesSubviews = true
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec
let verticalStackSpec = ASStackLayoutSpec.vertical()
verticalStackSpec.children = [
self.logoImage,
self.welcomeLabelNode,
// self.textFieldNode,
]
verticalStackSpec.alignItems = .stretch
verticalStackSpec.justifyContent = .spaceBetween
self.backgroundColor = .yellow
let displayInset = ASInsetLayoutSpec(
insets: UIEdgeInsets(top: 24, left: 0, bottom: 0, right: 0),
child: verticalStackSpec
)
return ASInsetLayoutSpec(insets: safeAreaInsets, child: displayInset)
private let logoImage: ASImageNode =
let imageNode = ASImageNode()
imageNode.image = UIImage(named: "logo")
imageNode.frame.size = CGSize(
width: CGFloat(SizeScaler().moderateScale(size: 98)),
height: CGFloat(SizeScaler().moderateScale(size: 48))
)
imageNode.contentMode = .scaleAspectFill
imageNode.style.alignSelf = .center
return imageNode
()
func hideWelcomeLabelNode()
self.welcomeLabelNode.setHide(visibility: true)
self.welcomeLabelNode.transitionLayout(withAnimation: true, shouldMeasureAsync: false)
func showWelcomeLabelNode()
self.welcomeLabelNode.setHide(visibility: false)
self.welcomeLabelNode.transitionLayout(withAnimation: true, shouldMeasureAsync: false)
// MARK: - WelcomeLabel
class WelcomeLabelNode: ASDisplayNode
var isHide: Bool = false
override required init()
super.init()
self.automaticallyManagesSubnodes = true
self.autoresizesSubviews = true
self.shouldAnimateSizeChanges = true
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec
let verticalStackSpec = ASStackLayoutSpec.vertical()
verticalStackSpec.children = [self.welcomeTitleLabel, self.welcomeDescLabel]
verticalStackSpec.alignItems = .start
self.backgroundColor = .green
return ASInsetLayoutSpec(
insets: UIEdgeInsets(top: 0, left: 0, bottom: 40, right: 0),
child: verticalStackSpec
)
override func animateLayoutTransition(_ context: ASContextTransitioning)
if (self.isHide)
let initialTitle = context.initialFrame(for: self.welcomeTitleLabel)
let initialDesc = context.initialFrame(for: self.welcomeDescLabel)
self.welcomeTitleLabel.alpha = 1
self.welcomeTitleLabel.frame = initialTitle
self.welcomeDescLabel.alpha = 1
self.welcomeDescLabel.frame = initialDesc
var finalTitle = context.finalFrame(for: self.welcomeTitleLabel)
finalTitle.origin.y -= 50
var finalDesc = context.finalFrame(for: self.welcomeDescLabel)
finalDesc.origin.y -= 50
UIView.animate(withDuration: 0.4, animations:
self.welcomeTitleLabel.alpha = 0
self.welcomeTitleLabel.frame = finalTitle
self.welcomeDescLabel.alpha = 0
self.welcomeDescLabel.frame = finalDesc
, completion: finished in
context.completeTransition(finished)
)
else
var finalTitle = context.finalFrame(for: self.welcomeTitleLabel)
finalTitle.origin.y -= 50
var finalDesc = context.finalFrame(for: self.welcomeDescLabel)
finalDesc.origin.y -= 50
self.welcomeTitleLabel.alpha = 0
self.welcomeTitleLabel.frame = finalTitle
self.welcomeDescLabel.alpha = 0
self.welcomeDescLabel.frame = finalDesc
let initialTitle = context.initialFrame(for: self.welcomeTitleLabel)
let initialDesc = context.initialFrame(for: self.welcomeDescLabel)
UIView.animate(withDuration: 0.4, animations:
self.welcomeTitleLabel.alpha = 1
self.welcomeTitleLabel.frame = initialTitle
self.welcomeDescLabel.alpha = 1
self.welcomeDescLabel.frame = initialDesc
, completion: finished in
context.completeTransition(finished)
)
let welcomeTitleLabel: QlueWorkLabel =
let label = QlueWorkLabel()
label.setFont34(text: "Selamat datang!", fontType: "medium")
label.textContainerInset = UIEdgeInsets(top: 32, left: 0, bottom: 8, right: 0)
label.style.flexGrow = 1
label.style.flexShrink = 1
label.backgroundColor = .cyan
return label
()
let welcomeDescLabel: QlueWorkLabel =
let label = QlueWorkLabel()
label.setFont16or20(
text: "Pantau pekerjaanmu lebih mudah dengan QlueWork",
fontType: "regular"
)
label.style.flexGrow = 1
label.style.flexShrink = 1
label.backgroundColor = .blue
return label
()
func setHide(visibility: Bool)
self.isHide = visibility
我希望父节点在子节点像 flexBox 一样隐藏/显示时重新调整布局。 谁能帮助我或告诉我为什么我做错了?
【问题讨论】:
【参考方案1】:渲染完成后,你不能指望parentNode
通过改变其子维度来调整自己
但您可以通过询问parentNode
重新渲染自身来完成工作
像这样
DispatchQueue.main.async
parentNode.transitionLayout(withAnimation: false,
shouldMeasureAsync: true,
measurementCompletion: nil)
确保在 main thread
上运行 transitionLayout
快乐纹理
【讨论】:
以上是关于Swift Readjust / Resize layout (ASDisplayNode) on show hide of children node的主要内容,如果未能解决你的问题,请参考以下文章
Swift 5 MacOS Image Resize 内存问题
text ORCL - Voir l'espace que l'on peux gagner en faisant un resize de DBF(avec generation