通过将UIView过渡添加到UIStackView来对其进行动画处理

时间:2019-06-28 15:17:30

标签: ios swift autolayout frame uistackview

我有一个自定义对象,它是UIView的子类。我想要的行为是使该对象最初出现在屏幕中间。然后,在3秒钟后,我希望对象(通过平滑的动画)过渡到其中已经包含元素的水平UIStackView,因此customObject最好移到{{ 1}}。

enter image description here

我目前无法实现此行为。

ViewController.swift

stackView

1 个答案:

答案 0 :(得分:0)

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

因此,一个选项:

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

enter image description here

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

//
//  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
            }
        })

    }

}