Zack Shapiro
Zack Shapiro

Reputation: 6998

Entire view is animating in from the top-left

Hey there internet reader,

I'm building a small feature where my banner animates in from the top using Snapkit and Combine. In my viewDidLoad, I call setupObservers which creates this publisher below.

Deeper in my app, isShown is toggled so that the publisher fires when the view is seen for the first time, causing not just the banner but the entire view to animate in from the top left, 0,0 position.

I know this is because I'm calling self.view.layoutIfNeeded(), I'm just curious how to mitigate this so I can get the view to load in without animation, then show the banner.

Thanks!

    public override func viewDidLoad() {
        super.viewDidLoad()

        setupObservers()

        viewStore.send(.viewDidLoad)
    }
        viewStore.publisher
            .banner
            .isShown
            .sink { isShown in
                guard self.initLoadFinished else { return }

                UIView.animate(withDuration: Metrics.animationDuration, delay: 0, options: .curveEaseInOut) {
                    self.banner.snp.updateConstraints {
                        if isShown {
                            self.topConstraint = $0.top.equalToSuperview()
                        } else {
                            self.topConstraint = $0.top.equalToSuperview().offset(-Metrics.bannerHeight)
                        }
                    }
                    self.view.layoutIfNeeded()
                }
            }.store(in: &cancellables)

Upvotes: 0

Views: 654

Answers (1)

Shehata Gamal
Shehata Gamal

Reputation: 100533

Get setting the constant out of the animation block

self.banner.snp.updateConstraints {
    if isShown {
         self.topConstraint.update(offset: 0)  
    } else {
         self.topConstraint.update(offset:-Metrics.bannerHeight)
    }
}  
UIView.animate(withDuration: Metrics.animationDuration, delay: 0, options: .curveEaseInOut) { 
    self.view.layoutIfNeeded() 
}

Upvotes: 1

Related Questions