Ctshaw
Ctshaw

Reputation: 217

IOS equivalent of Android's Shared element transition

I was wondering if IOS has any type of transition animation similar to Android's Shared element transition. For those not familiar with what that is, it is essentially "reusing" a view from one screen to another. For example the text from your list on screen A is the header text on screen B, it will translate and scale the text so that it looks like it is moving into its proper place.

Upvotes: 4

Views: 7049

Answers (2)

Markymark
Markymark

Reputation: 2989

For my scenario I simply needed to enlarge an image. The below code offers a quick/simple way to enlarge/shrink a photo w/out needing to use a library. The view is enlarged up to the width of the screen.

Leaving this here in case it helps anyone else.

extension UIView {

    func enlarge() {
        let maxWidth = superview?.bounds.width ?? self.bounds.width + 100

        UIView.animate(withDuration: 0.5, animations: {() -> Void in
            let factor = maxWidth / self.bounds.width
            self.transform = CGAffineTransform(scaleX: factor, y: factor)
        })
    }

    func resetSize() {
        UIView.animate(withDuration: 0.5, animations: {() -> Void in
            self.transform = CGAffineTransform(scaleX: 1, y: 1)
        })
    }
}

With a little bit more work we can also make the image always be enlarged in the center of the screen and then shrink back to the original position.

extension UIView {

    func enlarge(_ shouldEnlarge: Bool, _ originalY: CGFloat = -1) {
        if(shouldEnlarge) {
            enlarge()
        }
        else {
            resetSize(originalY)
        }
    }

    //View must be contained in a parent
    func enlarge() {
        guard let parent = superview else { return }

        let maxWidth = parent.bounds.width
        let newY =  parent.bounds.height / 2 -  maxWidth / 2

        UIView.animate(withDuration: 0.5, animations: {() -> Void in
            let factor = maxWidth / self.bounds.width
            self.transform = CGAffineTransform(scaleX: factor, y: factor)
            self.frame.origin.y = newY
        })
    }

    //pass in the original view.frame.origin.y to animate back to the correct position
    func resetSize(_ originalY: CGFloat = -1) {
        UIView.animate(withDuration: 0.5, animations: {() -> Void in
            self.transform = CGAffineTransform(scaleX: 1, y: 1)
            if(originalY != -1) {
                self.frame.origin.y = originalY
            }
        })
    }
}

Upvotes: 0

Christopher Harris
Christopher Harris

Reputation: 682

You can accomplish this same technique using auto-layout constraints.

You can render a view on screen A at a small size (let's say in a list). Then when the user taps on this view to segue to screen B, you can render the view as the size of the screen.

Using different auto-layout priorities, you can accomplish different layouts depending on the size of the view.

Upvotes: 3

Related Questions