gpt4 book ai didi

ios - UIView 仅在一个 View Controller 中设置动画

转载 作者:行者123 更新时间:2023-11-28 07:24:59 25 4
gpt4 key购买 nike

所以我在 swift 中使用容器 View 来获取在导航 Controller 中的多个 View Controller 之间共享的叠加 View 。

它的工作方式是我有许多 subview 为流程创建“背景”。在这些 View 之上,我有一个容器 View ,其中嵌入了一个导航 Controller 。该导航 Controller 通过多个 View Controller 引导用户完成入职流程。在这个容器 View 之上是“进度 View ”,它的前缘与父 View 的前缘对齐,并且随着用户在引导过程中导航而增加宽度,直到最终,栏的宽度等于屏幕的宽度并且用户已经创建了他们的个人资料。这是它的外观示例: Skip to 1:53 to see the main issue

这是包含 View Controller 的样子。注意背景的分层,然后是容器 View ,然后是进度条 View : enter image description here

这个 View Controller 有一个名为 updateProgressBar 的函数,它获取一定比例的屏幕宽度来设置动画,然后执行动画。

func updateProgressBar(to percentAsDecimal: CGFloat!) {
UIView.animate(withDuration: 0.25) {
self.progressBarWidth.constant = self.view.frame.width * percentAsDecimal
self.view.layoutIfNeeded()
}
}

问题:因为包含的导航 Controller 在进度条的动画期间插入了一个新的 View Controller ,所以当这个新的 View Controller 布置它的 subview 时,这个布置是动画的。

我尝试过的:我创建了自定义类,它们是 UIView 的子类,使用 UIView.performWithoutAnimation 函数来避免这种 subview 动画。

import UIKit

class NonAnimatingView: UIView {
override func layoutSubviews() {
UIView.performWithoutAnimation {
super.layoutSubviews()
}
}
}

我用按钮做了类似的事情。

import UIKit

class NonAnimatingButton: UIButton {
override func layoutSubviews() {
UIView.performWithoutAnimation {
super.layoutSubviews()
}
}
}

但是,当我尝试使用 UISearchBar 执行此操作时,部分动画已解析,但不是全部。

import UIKit

class NonAnimatingSearchBar: UISearchBar {
override func layoutSubviews() {
UIView.performWithoutAnimation {
super.layoutSubviews()
}
}

override func addSubview(_ view: UIView) {
UIView.performWithoutAnimation {
super.addSubview(view)
}
}

override func insertSubview(_ view: UIView, at index: Int) {
UIView.performWithoutAnimation {
super.insertSubview(view, at: index)
}
}

override func insertSubview(_ view: UIView, aboveSubview siblingSubview: UIView) {
UIView.performWithoutAnimation {
super.insertSubview(view, aboveSubview: siblingSubview)
}
}

override func insertSubview(_ view: UIView, belowSubview siblingSubview: UIView) {
UIView.performWithoutAnimation {
super.insertSubview(view, belowSubview: siblingSubview)
}
}

override func sendSubviewToBack(_ view: UIView) {
UIView.performWithoutAnimation {
super.sendSubviewToBack(view)
}
}

override func bringSubviewToFront(_ view: UIView) {
UIView.performWithoutAnimation {
super.bringSubviewToFront(view)
}
}

override func exchangeSubview(at index1: Int, withSubviewAt index2: Int) {
UIView.performWithoutAnimation {
super.exchangeSubview(at: index1, withSubviewAt: index2)
}
}
}

我还确保在推送导航 Controller View Controller 之前调用的任何布局更改都不会被动画化:

override func viewDidLoad() {
UIView.performWithoutAnimation {
super.viewDidLoad()
femaleButton.backgroundColor = UIColor.lightGray.withAlphaComponent(0.25)
maleButton.backgroundColor = UIColor.lightGray.withAlphaComponent(0.25)
otherGenderButton.backgroundColor = UIColor.lightGray.withAlphaComponent(0.25)
femaleButton.layer.cornerRadius = 5
maleButton.layer.cornerRadius = 5
otherGenderButton.layer.cornerRadius = 5
nextButton.layer.cornerRadius = nextButton.frame.height/2
}
}

我想知道的是:有没有我可以调用而不是 UIView.animate 的东西,这样我就可以在指定的 View Controller 中设置动画而不影响当前可见的所有 View Controller ?如果不是,解决此问题的最佳方法是什么?

最佳答案

因此,我最终采纳了@rs7 的建议并改用了CAShapeLayer。我没有使用界面生成器,而是继续创建一个 CAShapeLayer 并将其添加到 viewDidLayoutSubviews()

var progressBar: CAShapeLayer!

override func 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)
}

然后我继续更新 updateProgressBar 以调整 CALayer 的大小,而不是 NSLayoutConstraint 常量。

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 = false
anim.fillMode = .forwards
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")
}

现在,不再需要我的自定义 NonAnimatingViewNonAnimatingButtonNonAnimatingSearchBar。 :)

关于ios - UIView 仅在一个 View Controller 中设置动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56841929/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com