我正在制作一个应用程序,通过一系列步骤引导用户创建帐户。完成每个步骤后,用户将被带到下一个 View Controller ,并且屏幕顶部会出现一个进度条动画,以传达已完成的帐户创建过程的多少。这是最终结果:
这是通过在包含 View 中放置导航 Controller 来实现的。进度条覆盖在包含 View 上,每次导航 Controller 推送一个新的 View Controller 时,它都会告诉包含 View Controller 将进度条设置为父 View 宽度的某个百分比。这是通过以下 updateProgressBar
函数完成的。
import UIKit
class ContainerVC: UIViewController {
var progressBar: CAShapeLayer!
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
progressBar = CAShapeLayer()
progressBar.bounds = CGRect(x: 0, y: 0, width: 0, height: view.safeAreaInsets.top)
progressBar.position = CGPoint(x: 0, y: 0)
progressBar.anchorPoint = CGPoint(x: 0, y: 0)
progressBar.backgroundColor = UIColor.secondaryColor.cgColor
view.layer.addSublayer(progressBar)
}
func updateProgressBar(to percentAsDecimal: CGFloat!) {
let newWidth = view.bounds.width * percentAsDecimal
CATransaction.begin()
CATransaction.setCompletionBlock({
self.progressBar.bounds.size.width = newWidth
})
CATransaction.commit()
let anim = CABasicAnimation(keyPath: "bounds")
anim.isRemovedOnCompletion = true
anim.duration = 0.25
anim.fromValue = NSValue(cgRect: CGRect(x: 0, y: 0, width: progressBar.bounds.width, height: view.safeAreaInsets.top))
anim.toValue = NSValue(cgRect: CGRect(x: 0, y: 0, width: newWidth, height: view.safeAreaInsets.top))
progressBar.add(anim, forKey: "anim")
}
}
导航 Controller 堆栈中的 View Controller 将在推送下一个 VC 时调用此 updateProgressBar
函数。这样做是这样的:
class FourthViewController: UIViewController {
var containerVC: ContainerViewController!
...
@IBAction func nextButtonPressed(_ sender: Any) {
let storyboard = UIStoryboard(name: "Main", bundle: .main)
let fifthVC = storyboard.instantiateViewController(withIdentifier: "FifthVC") as! FifthViewController
fifthVC.containerVC = containerVC
navigationController!.pushViewController(fifthVC, animated: true)
//We pass 5/11 because the next step will be step 5 out of 11 total steps
self.containerVC.updateProgressBar(to: 5/11)
}
}
同理,当按下返回键时,我们收缩容器VC的进度条:
class FourthViewController: UIViewController {
var containerVC: ContainerViewController!
...
@IBAction func backButtonPressed(_ sender: Any) {
navigationController!.popViewController(animated: true)
//We pass 3/11 because the previous step is step 3 out of 11 total steps
containerVC.updateProgressBar(to: 3/11)
}
}
我的问题是这个动画有时只能工作。进度条在进程中向前移动时始终有效,但有时,当用户向后导航时,进度条会卡住并且不会再向任一方向移动,直到出现未到达的 View Controller 。请看下面的视频:
Video of Bug (Bug begins around 0:23)
我已确认警报 Controller 的显示不是动画失败的原因,并且还确保动画正在主线程上发生。有什么建议吗?
正如这个答案中很好解释的 here , viewDidLayoutSubviews()
被多次调用。
在您的情况下,每次您从导航堆栈中推送或弹出 View Controller 时,您最终都会实例化一个新的 CAShapeLayer
。
尝试改用 viewDidAppear()
。
关于ios - CABasicAnimation 有时有效,有时失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57777822/
欢迎光临 OStack程序员社区-中国程序员成长平台 (https://ostack.cn/) | Powered by Discuz! X3.4 |