Wazza
Wazza

Reputation: 1885

Animate view to hide/scale into its bottom right corner

I'm trying to get a view to shrink down to nothing in the bottom right corner when its cancel button is pressed. Currently when i use:

    UIView.animate(withDuration: 0.7, delay: 0, options: .beginFromCurrentState, animations: {
        self.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)
    })

the view shrinks into its center.

I understand that I should be setting the anchor point of the layer so it shrinks to that point but when I do this it moves the view center to that point then shrinks:

    UIView.animate(withDuration: 0.7, delay: 0, options: .beginFromCurrentState, animations: {
        self.layer.anchorPoint = CGPoint(x: 0.0, y: 0.0)
        self.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)
    })

Any ideas?

Edit: More info would be that im using cartography to set the view's constraints to the viewController.view edges, I'm wondering if this has something to do with it?

Upvotes: 0

Views: 1632

Answers (1)

Sandeep
Sandeep

Reputation: 21144

Frame of UIView or CALayer are actually derived properties which are calculated from layers position and anchorpoint. So, when you change either one of these, the layer frame also changes and hence you see the effect of view movement.

When you change the anchor point of the CALayer, you could also immediately set the position of the layer to compromise for the change. You can offset the view position with amount of anchor point changes relative to views bounds.

Here is a simple extension on UIView, which you could use to change the layers anchor point without actually changing the position.

extension UIView {

    func set(anchorPoint: CGPoint) {

        let originalPosition = CGPoint(x: frame.midX, y: frame.midY)

        let width = bounds.width
        let height = bounds.height

        let newXPosition = originalPosition.x +  (anchorPoint.x - 0.5) * width
        let newYPosition = originalPosition.y + (anchorPoint.y - 0.5) * height

        layer.anchorPoint = anchorPoint

        layer.position = CGPoint(x: newXPosition,
                                 y: newYPosition)
    }
}

The code above changes position of CALayer as soon as you make change to the anchorPoint. You could as well do this without having to change the position.

Whenever you set the anchorPoint, simply set back previous frame,

let originalFrame = view.frame
view.layer.anchorPoint = CGPoint(x: 0, y: 0)
view.frame = originalFrame

This will prevent your view from moving and stay at the same position, despite of the change in anchorPoint.

Also, for your particular case, setting anchorPoint to layer triggers intrinsic animation. So, if you want to make it like shrink to lower or upper edge, perform anchorPoint change before animation like so,

    UIView.performWithoutAnimation {
        self.set(anchorPoint: CGPoint(x: 0, y: 0))
    }

    UIView.animate(withDuration: 0.7, delay: 0, options: .beginFromCurrentState, animations: {
        self.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)
    })

Upvotes: 5

Related Questions