更改viewController时保持动画

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

我正在尝试在个人资料图片后面编写一个

animation
,以鼓励用户单击它。 这是一个逐渐变大和变小的圆圈。

override func layoutSubviews() {
  super.layoutSubviews()

  UIView.animate(withDuration: 1.0, delay: 0, options: [.repeat, .autoreverse], animations: {

     self.bouncedView.transform = CGAffineTransform(scaleX:
        1.3, y: 1.3)

      }, completion: nil)

}

问题是,当我转到另一个

viewController
时,动画停止,圆圈保持在屏幕截图上。你知道我怎样才能避免这个问题吗?

ios swift animation swift3 uiviewcontroller
3个回答
2
投票

在 ViewDidAppear 上转换为 .identity。类似于下面的代码:

class HomeController: UIViewController {

@IBOutlet weak var viewToAnimate: UIView!
override func viewDidLoad() {
    super.viewDidLoad()
}

override func viewWillAppear(_ animated: Bool) {
    self.viewToAnimate.transform = .identity
    animateView()
}

func animateView(){
    UIView.animate(withDuration: 1.0, delay: 0, options: [.repeat, .autoreverse], animations: {

        self.viewToAnimate.transform = CGAffineTransform(scaleX:
            1.3, y: 1.3)

    }, completion: nil)
}

}

您可能已经猜到的问题是 UIView.animate 仅在 ViewDidLoad 方法上调用,并且由于我们在从另一个 ViewController 返回时无法访问该代码,因此最好在 ViewWillAppear 方法中启动动画.

如果在选项卡之间切换时出现相同的问题,请为要设置动画的视图创建一个单独的 UIView 子类,然后按以下步骤操作:

class AnimateView: UIView {

override func awakeFromNib() {
    super.awakeFromNib()
}

override func willMove(toWindow newWindow: UIWindow?) {
    super.willMove(toWindow: newWindow)
    self.transform = .identity
    animateView()
}

func animateView(){
    UIView.animate(withDuration: 1.0, delay: 0, options: [.repeat, .autoreverse], animations: {

        self.transform = CGAffineTransform(scaleX:
            1.3, y: 1.3)

    }, completion: nil)
}

}

在这里,您已将 animate 函数应用于 UIView 对象,每当视图出现时,动画就会重置。


0
投票

嗯,我还没有一个令人满意的答案(至少这会让我满意),但我想至少添加一些我通过一些实验获得的见解。

首先,当

viewController
不是当前呈现的动画时,动画似乎就结束了。在您的情况下,这意味着动画停止并以视图放大 1.3 倍的状态结束,并停止重复。仅当您第一次展示时,
layoutSubviews
才会被调用。至少
viewController.viewDidLayoutSubviews
仅在开始时被调用,而不是在您返回时被调用(因此当视图重新出现时
layoutSubviews
将不会被执行) - 因此动画不会重新启动。

我尝试将动画移动到

viewDidAppear
UIViewController
- 这也不起作用,因为停止动画会导致视图已缩放 1.3 倍的状态。在创建动画之前将状态重置为
CGAffineTransform.identity
确实有效。

现在正如我所说,这可以作为您如何使其工作的解决方法,但是,我认为您真正正在寻找的是一些钩子,可以告诉您的视图(而不是 viewController)它再次呈现。但下面这个最小的例子至少可以帮助其他人看一下,而不是从头开始。

import UIKit
import PlaygroundSupport

class MyViewController : UIViewController {

    let animator = UIViewPropertyAnimator(duration: 1, timingParameters: UICubicTimingParameters(animationCurve: .linear))

    init(title: String) {
        super.init(nibName: nil, bundle: nil)
        self.title = title
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    let animatableView = UIView()

    override func loadView() {
        let view = UIView()
        view.backgroundColor = .white

        animatableView.frame = CGRect(x: 150, y: 400, width: 100, height: 100)
        animatableView.backgroundColor = UIColor.magenta
        view.addSubview(animatableView)

        self.view = view
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        self.animatableView.transform = CGAffineTransform.identity
        UIView.animate(withDuration: 1.0, delay: 0, options: [.repeat, .autoreverse], animations: {
            self.animatableView.transform = CGAffineTransform(scaleX:
                1.3, y: 1.3)
        }, completion: nil)
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        print("\(self.title) >> Lay out")
    }
}

let tabBar = UITabBarController()
tabBar.viewControllers = [MyViewController(title: "first"), MyViewController(title: "second"), MyViewController(title: "third")]
tabBar.selectedIndex = 0
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = tabBar

编辑

我添加了几行来检查

self.animatableView.layer.animationKeys()
是否包含任何动画,似乎切换选项卡会从视图层中删除动画 - 所以你必须找到一种方法在每次视图重新出现时添加动画。

编辑2 所以我会同意@SWAT的答案并使用

willMove(toWindow:)
而不是
layoutSubviews


0
投票

您可以添加完成块,您将在其中创建第一个视图状态。例如:

UIView.animate(withDuration:1.0,延迟:0,选项:[.repeat,.autoreverse],动画:{

 self.bouncedView.transform = CGAffineTransform(scaleX:
    1.3, y: 1.3)

  } completion: { _ in
        self.bouncedView.transform = CGAffineTransform(scaleX:
    1.0, y: 1.0)
    }
© www.soinside.com 2019 - 2024. All rights reserved.