aleksy.t
aleksy.t

Reputation: 277

Cannot animate properly when using SnapKit

I'm trying to animate a logo (UILabel) for my app, from the middle to the top. What I tried was to update the constraint but it doesn't seem to work. The problem is the animation i.e. logo, goes from the origin (0,0) and not the middle of the view to the top. The necessary code (the controller and the class it inherits):

import UIKit
import SnapKit

class EntryController: LatroController {

    static let spacingFromTheTop: CGFloat = 150
    var latroLabelCenterYConstraint: Constraint?

    override init() {
        super.init()
        self.animateTitleLabel()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func initTitleLabel() {
        self.latroLabel = UILabel()
        self.latroLabel?.text = General.latro.rawValue
        self.latroLabel?.textAlignment = .center
        self.latroLabel?.font = UIFont (name: General.latroFont.rawValue, size: EntryController.fontSize)
        self.latroLabel?.textColor = .white
        self.latroLabel?.contentMode = .center
        self.view.addSubview(self.latroLabel!)

        self.latroLabel?.snp.makeConstraints({ (make) in
            make.width.equalTo(EntryController.latroWidth)
            make.height.equalTo(EntryController.latroHeight)
            make.centerX.equalTo(self.view.center.x)
            self.latroLabelCenterYConstraint = make.centerY.equalTo(self.view.center.y).constraint
        })
    }

    func animateTitleLabel() {
        UIView.animate(withDuration: 1.5) {
            self.latroLabel?.snp.updateConstraints { (make) in
                make.centerY.equalTo(200)
            }
            self.view.layoutIfNeeded()
        }
    }
}

import UIKit
import SnapKit

class LatroController: UIViewController {

static let latroWidth: CGFloat = 288
static let latroHeight: CGFloat = 98
static let btnWidth: CGFloat = 288
static let btnHeight: CGFloat = 70
static let txtFieldWidth: CGFloat = 288
static let txtFieldHeight: CGFloat = 50
static let fontSize: CGFloat = 70
static let bottomOffset: CGFloat = 100
static let buttonOffset: CGFloat = 20
static let logoOffset: CGFloat = 50

var latroLabel: UILabel?
var signUpBtn: UIButton?
var logInBtn: UIButton?
var titleLabelYConstraint: NSLayoutConstraint?
var usernameTxtField: UITextField?

init() {
    super.init(nibName: nil, bundle: nil)
    self.view.backgroundColor = UIColor(named: General.orange.rawValue)
    self.initTitleLabel()
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    self.navigationController?.setNavigationBarHidden(true, animated: false)
}

override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)
    self.navigationController?.setNavigationBarHidden(false, animated: true)
}

func initTitleLabel() {
    self.latroLabel = UILabel()
    self.latroLabel?.text = General.latro.rawValue
    self.latroLabel?.textAlignment = .center
    self.latroLabel?.font = UIFont (name: General.latroFont.rawValue, size: EntryController.fontSize)
    self.latroLabel?.textColor = .white
    self.latroLabel?.contentMode = .center
    self.view.addSubview(self.latroLabel!)

    self.latroLabel?.snp.makeConstraints({ (make) in
        make.width.equalTo(LatroController.latroWidth)
        make.height.equalTo(LatroController.latroHeight)
        let safeAreaLayoutHeight = self.view.safeAreaLayoutGuide.layoutFrame.height
        print(safeAreaLayoutHeight)
        make.top.equalTo(self.view).offset(150)
        make.centerX.equalTo(self.view.center.x)
    })
}
}

Upvotes: 0

Views: 2043

Answers (2)

matt
matt

Reputation: 535511

You cannot animate a view until it is in the interface and initial layout has been performed. Thus you are calling self.animateTitleLabel() way too soon (in init).

Call it in something like viewDidAppear. Of course then you must use a Bool flag property to make sure you don't call it every time viewDidAppear runs, only the first time.

(It might be necessary to call it in viewDidLayoutSubviews instead; you'll have to experiment.)

Upvotes: 2

aleksy.t
aleksy.t

Reputation: 277

Okay, thought it would be tougher than I initially expected. The following was missing:

self.view.updateLayoutIfNeeded() 

after setting constraints!

Upvotes: 1

Related Questions