通过将 UIView 过渡添加到 UIStackView 来制作动画

Posted

技术标签:

【中文标题】通过将 UIView 过渡添加到 UIStackView 来制作动画【英文标题】:Animate UIView transition by adding it to a UIStackView 【发布时间】:2019-06-28 15:17:30 【问题描述】:

我有一个自定义对象,它是UIView 的子类。我想要的行为是让这个对象最初出现在屏幕中间。然后,在 3 秒后,我希望对象转换(带有平滑动画)到已经有一个元素的水平 UIStackView,所以 customObject 理想情况下会移动到 stackView 的右半部分。

我目前无法实现此行为。

ViewController.swift

class ViewController: UIViewController 

    let customObject = CustomObject(frame: .init(x: 0, 
                                                 y: 0, 
                                                 width: 200.0, 
                                                 height: 200.0))

    let stackView: UIStackView = 
        let sv = UIStackView()
        sv.axis = .horizontal
        return sv
    () 

    override func viewDidLoad() 
        super.viewDidLoad()

        let label = UILabel()
        label.text = "first Element in horizontal stackView"
        stackView.addArrangedSubview(label)

        addCustomObjectToStackView()
    

    func addCustomObjectToStackView() 

        stackView.addArrangedSubview(customObject)

        UIView.animate(withDuration: 1.0, animations: 
            customObject.layoutIfNeeded()
        )
    

【问题讨论】:

张贴一张你希望它在开始时的样子,以及你希望它在动画后的样子。它真的需要在堆栈视图中结束吗? 是的,我绝对希望它最终出现在 stackView 中。我知道如何为UIView 设置动画,否则。另外,我会发布一张图片 给你@DonMag 【参考方案1】:

由于UIStackView 旨在安排其子视图,因此以这种方式进行动画添加可能很难完成。

所以,一个选择:

在 stackView 中以明确的“holderView”开头 将您的 customObject 添加到主视图(它现在是 stackView 的兄弟) 动画customObject的位置和大小以匹配holderView 在动画完成时,添加customObject 作为holderView 的子视图

这里有一些示例代码可供试用(注意:只是演示代码,尚未准备好用于生产):

//
//  AnimToStackViewController.swift
//
//  Created by Don Mag on 6/28/19.
//

import UIKit

class CustomObject: UIView 

    override init(frame: CGRect) 
        super.init(frame: frame)

        let theLabel = UILabel()
        theLabel.textAlignment = .center
        theLabel.text = "Custom Object"
        theLabel.translatesAutoresizingMaskIntoConstraints = false

        addSubview(theLabel)

        NSLayoutConstraint.activate([
            theLabel.centerXAnchor.constraint(equalTo: centerXAnchor),
            theLabel.centerYAnchor.constraint(equalTo: centerYAnchor),
            ])

        backgroundColor = .cyan
    

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



class AnimToStackViewController: UIViewController 

    let theStackView: UIStackView = 
        let v = UIStackView()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.axis = .horizontal
        v.alignment = .fill
        v.distribution = .fill
        return v
    ()

    let theLabel: UILabel = 
        let v = UILabel()
        v.textAlignment = .center
        v.text = "This is the label in the stack view."
        v.numberOfLines = 0
        return v
    ()

    let holderView: UIView = 
        let v = UIView()
        v.translatesAutoresizingMaskIntoConstraints = false
        return v
    ()

    let customObject = CustomObject(frame: CGRect(x: 0, y: 0, width: 150, height: 150))

    override func viewDidLoad() 
        super.viewDidLoad()

        view.addSubview(theStackView)

        theStackView.addArrangedSubview(theLabel)
        theStackView.addArrangedSubview(holderView)

        view.addSubview(customObject)

        NSLayoutConstraint.activate([
            theStackView.widthAnchor.constraint(equalToConstant: 300.0),
            theStackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 80.0),
            theStackView.centerXAnchor.constraint(equalTo: view.centerXAnchor),

            holderView.widthAnchor.constraint(equalTo: customObject.widthAnchor, constant: 0.0),
            holderView.heightAnchor.constraint(equalTo: customObject.heightAnchor, constant: 0.0),
            ])

        customObject.center = view.center

    

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

        let pt = self.holderView.center
        let convertedPoint = self.theStackView.convert(pt, to: self.view)

        UIView.animate(withDuration: 1.0, delay: 3.0, options: [], animations: 
            self.customObject.center = convertedPoint
            self.view.layoutIfNeeded()
        , completion:  (finished) in
            if finished 
                self.holderView.addSubview(self.customObject)
                self.customObject.frame = self.holderView.bounds
            
        )

    


【讨论】:

感谢您的详细解答!我正在尝试。会尽快通知您

以上是关于通过将 UIView 过渡添加到 UIStackView 来制作动画的主要内容,如果未能解决你的问题,请参考以下文章

iPhone横向UIView幻灯片过渡

从一个 UIView 到另一个 UIView 的平滑过渡

UIView 过渡动画

如何在覆盖 UIView 之前停止幻灯片过渡到 Second VC?

UIView 滑动过渡淡出

UIView 过渡动画