class OnboardingWelcomeMessageStackView: UIStackView {
private lazy var retriggerAnimation = true
let messageHeader: UILabel = {
let label = UILabel()
label.text = OnboardingConstants.chatbotGreeting
label.textColor = .white
label.font = UIFont.boldSystemFont(ofSize: 24)
label.alpha = 0
label.numberOfLines = 0
label.textAlignment = .center
label.sizeToFit()
return label
}()
let messageBody: UILabel = {
let label = UILabel()
label.text = OnboardingConstants.chatbotPurpose
label.textColor = .white
label.font = UIFont.systemFont(ofSize: 16, weight: .medium)
label.alpha = 0
label.numberOfLines = 0
label.textAlignment = .center
label.sizeToFit()
return label
}()
override init(frame: CGRect) {
super.init(frame: frame)
setupStackview()
animateOnLoad()
}
required init(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func animateOnLoad() -> Void {
let duration: TimeInterval = 7
UIView.animateKeyframes(withDuration: duration, delay: 0.3, options: .calculationModeLinear, animations: {
UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 1 / duration, animations: {
self.messageHeader.alpha = 1
})
UIView.addKeyframe(withRelativeStartTime: 3 / duration, relativeDuration: 1 / duration, animations: {
self.messageBody.alpha = 1
})
UIView.addKeyframe(withRelativeStartTime: 6 / duration, relativeDuration: 1 / duration, animations: {
if self.retriggerAnimation {
self.messageHeader.alpha = 0
self.messageBody.alpha = 0
}
})
}) { (_) in
if self.retriggerAnimation {
self.updateLabelText()
self.animateOnLoad()
}
}
}
fileprivate func updateLabelText() -> Void {
retriggerAnimation = false
messageHeader.text = OnboardingConstants.chatbotIntroduction
messageBody.text = OnboardingConstants.chatbotOnboardingWelcome
}
fileprivate func setupStackview() -> Void {
self.addArrangedSubview(messageHeader)
self.addArrangedSubview(messageBody)
}
}
本质上,一旦添加了视图,我将调用
animateOnLoad
,然后使用设置的属性再次调用它以防止其再次运行。这感觉很hacky,老实说我不喜欢这样。我怎样才能达到这种效果?什么是最佳实践/最有效的方法?
最佳答案
最佳实践始终是在涉及此类问题时引入本地推理。
因此,您可以像这样创建自定义动画功能。
private func fade(labels : UILabel..., toAlpha alpha : CGFloat, duration : TimeInterval, completion : ((Bool)->Void)?){
UIView.animate(withDuration: duration, animations: {
labels.forEach({$0.alpha = alpha})
}, completion: completion)
}
然后像这样在viewDidAppear中调用该函数
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
fade(labels: label1, toAlpha: 1, duration: 1) { (_) in
self.fade(labels: self.label2, toAlpha: 1, duration: 1, completion: { (_) in
self.fade(labels: self.label1, self.label2, toAlpha: 0, duration: 1, completion: { (_) in
self.fade(labels: self.label1, toAlpha: 1, duration: 1, completion: { (_) in
self.fade(labels: self.label2, toAlpha: 1, duration: 1, completion: nil)
})
})
})
}
}
我所写的将执行与您提供的完全相同的衰落序列。
您可以选择编写更好的帮助程序功能来分隔职责。.但是您应该明白
另外,请记住使用弱者或无人者解决保留周期问题。
关于swift - 淡入和淡出UILabel,每次更改屏幕上的文本,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53600887/