Reilaan
Reilaan

Reputation: 11

animated expanding of subview by action without constraints

I have a UIViewController with a UIScrollView as subview. the scrollview size and origin are computed properties.

override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        
        
        let sizeWidth = view.frame.size.width - (view.frame.size.width / 5)
        let sizeHeight = (view.frame.height / 5) * 3
        let originX = (view.width-sizeWidth) / 2
        
        // sizes & positions of container & subviews
        slideScrollView.frame = CGRect(x: originX,
                                      y: 50,
                                      width: sizeWidth,
                                      height: sizeHeight)

how it looks like

by tapping the sign in or login button, the scrollview should expand animated. but it is the opposite.

@objc private func loginButtonTapped() {
        UIView.animate(withDuration: 5, delay: 0, options: .allowAnimatedContent) {
            self.slideScrollView.frame.size.height += (self.view.frame.height / 5) * 1
        }
    }

this is the result

it should expand, but it sets back to the action height property and expand to regular size, i hope anyone can tell me why this happens and may have a solution.

Upvotes: 0

Views: 88

Answers (1)

Sandeep Bhandari
Sandeep Bhandari

Reputation: 20369

Thats because your viewDidLayoutSubviews gets called multiple times (In this case twice as I have noticed by adding debug statements) when you start your animation with UIView.animate(withDuration: and because you always reset the slideScrollView.frame in viewDidLayoutSubviews you see unnecessary side effects.

You can always check this by putting a break point in viewDidLayoutSubviews when loginButtonTapped gets triggered. Refer this question for similar explaination

If your intention to use viewDidLayoutSubviews is to know when view is properly loaded and its frames are updated properly you can always use

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        let sizeWidth = view.frame.size.width - (view.frame.size.width / 5)
        let sizeHeight = (view.frame.height / 5) * 3
        let originX = (view.width-sizeWidth) / 2
        
        // sizes & positions of container & subviews
        slideScrollView.frame = CGRect(x: originX,
                                      y: 50,
                                      width: sizeWidth,
                                      height: sizeHeight)
    }

Now your loginButtonTapped should work fine.

As per apple docs: viewDidLayoutSubviews Called to notify the view controller that its view has just laid out its subviews.

With that I think my explanation above makes sense, you use UIView.animate(withDuration: to modify the frame of scrollView so obviously View updates/re-renders the subViews hence viewDidLayoutSubviews gets called when you call UIView.animate(withDuration: and because of your frame update code in viewDidLayoutSubviews you see adverse side effects

Upvotes: 1

Related Questions