IOS 相当于 Android 的共享元素转换

IOS equivalent of Android's Shared element transition

我想知道 IOS 是否有任何类型的过渡动画类似于 Android 的共享元素过渡。对于那些不熟悉那是什么的人,它本质上是 "reusing" 从一个屏幕到另一个屏幕的视图。例如,屏幕 A 上列表中的文本是屏幕 B 上的 header 文本,它将翻译和缩放文本,使其看起来像是移动到正确的位置。

您可以使用自动布局约束来完成同样的技术。

您可以在屏幕 A 上以较小的尺寸呈现视图(比方说在列表中)。然后,当用户点击此视图以转到屏幕 B 时,您可以将视图渲染为屏幕大小。

使用不同的自动布局优先级,您可以根据视图的大小完成不同的布局。

对于我的方案,我只需要放大图像。 下面的代码提供了一种 quick/simple 方法来 enlarge/shrink 一张照片 w/out 需要使用一个库。视图放大至屏幕宽度。

将此留在此处以防对其他人有所帮助。

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)
        })
    }
}

再多做一些工作,我们也可以让图像始终在屏幕中央放大,然后再缩小到原来的位置。

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
            }
        })
    }
}