Commit 2e56fcd5 by Daniel Dahan

development: added snapshot and pressenting transition

parent 1e63fdbd
...@@ -88,7 +88,7 @@ public enum MotionAnimation { ...@@ -88,7 +88,7 @@ public enum MotionAnimation {
case zPosition(Int) case zPosition(Int)
case width(CGFloat) case width(CGFloat)
case height(CGFloat) case height(CGFloat)
case size(CGSize) case size(width: CGFloat, height: CGFloat)
} }
extension CALayer { extension CALayer {
...@@ -168,17 +168,11 @@ extension CALayer { ...@@ -168,17 +168,11 @@ extension CALayer {
fileprivate func motion(delay: TimeInterval, duration: TimeInterval, timingFunction: MotionAnimationTimingFunction, animations: [MotionAnimation]) { fileprivate func motion(delay: TimeInterval, duration: TimeInterval, timingFunction: MotionAnimationTimingFunction, animations: [MotionAnimation]) {
var t = delay var t = delay
var w: CGFloat = 0
var h: CGFloat = 0
for v in animations { for v in animations {
switch v { switch v {
case let .delay(time): case let .delay(time):
t = time t = time
case let .width(width):
w = width
case let .height(height):
h = height
default:break default:break
} }
} }
...@@ -192,6 +186,22 @@ extension CALayer { ...@@ -192,6 +186,22 @@ extension CALayer {
var tf = timingFunction var tf = timingFunction
var d = duration var d = duration
var w: CGFloat = s.width
var h: CGFloat = s.height
for v in animations {
switch v {
case let .width(width):
w = width
case let .height(height):
h = height
case let .size(width, height):
w = width
h = height
default:break
}
}
var px: CGFloat = s.position.x var px: CGFloat = s.position.x
var py: CGFloat = s.position.y var py: CGFloat = s.position.y
...@@ -272,12 +282,8 @@ extension CALayer { ...@@ -272,12 +282,8 @@ extension CALayer {
let zPosition = Motion.zPosition(index: index) let zPosition = Motion.zPosition(index: index)
zPosition.fromValue = s.value(forKey: MotionAnimationKeyPath.zPosition.rawValue) ?? NSNumber(integerLiteral: 0) zPosition.fromValue = s.value(forKey: MotionAnimationKeyPath.zPosition.rawValue) ?? NSNumber(integerLiteral: 0)
a.append(zPosition) a.append(zPosition)
case let .width(w): case let .width(_), .height(_), .size(_, _):
a.append(Motion.width(w)) a.append(Motion.size(CGSize(width: w, height: h)))
case let .height(h):
a.append(Motion.height(h))
case let .size(size):
a.append(Motion.size(size))
default:break default:break
} }
} }
......
...@@ -119,6 +119,43 @@ extension UIView { ...@@ -119,6 +119,43 @@ extension UIView {
motionTransition.animations = value motionTransition.animations = value
} }
} }
open func snapshot(view: UIView, afterUpdates: Bool) -> UIView {
view.isHidden = false
let oldCornerRadius = view.cornerRadius
view.cornerRadius = 0
let v = view.snapshotView(afterScreenUpdates: afterUpdates)!
view.cornerRadius = oldCornerRadius
let contentView = v.subviews.first!
contentView.cornerRadius = view.cornerRadius
contentView.masksToBounds = true
v.motionTransitionIdentifier = view.motionTransitionIdentifier
v.position = view.superview?.convert(view.position, to: nil) ?? view.position
v.bounds = view.bounds
v.cornerRadius = view.cornerRadius
v.zPosition = view.zPosition
v.opacity = view.opacity
v.isOpaque = view.isOpaque
v.anchorPoint = view.anchorPoint
v.layer.masksToBounds = view.layer.masksToBounds
v.borderColor = view.borderColor
v.borderWidth = view.borderWidth
v.shadowRadius = view.shadowRadius
v.shadowOpacity = view.shadowOpacity
v.shadowColor = view.shadowColor
v.shadowOffset = view.shadowOffset
v.contentMode = view.contentMode
v.layer.transform = view.layer.transform
view.isHidden = true
addSubview(v)
return v
}
} }
open class MotionTransitionPresentationController: UIPresentationController { open class MotionTransitionPresentationController: UIPresentationController {
...@@ -224,13 +261,13 @@ open class MotionTransitionAnimator: MotionTransitionDelegate { ...@@ -224,13 +261,13 @@ open class MotionTransitionAnimator: MotionTransitionDelegate {
open var transitionView = UIView() open var transitionView = UIView()
public var toViews: [UIView] { public var toViews: [UIView] {
var views: [UIView] = 0 < toViewController.view.motionTransitionIdentifier.utf16.count ? [toViewController.view] : [] var views: [UIView] = []
subviews(of: toViewController.view, views: &views) subviews(of: toViewController.view, views: &views)
return views return views
} }
public var fromViews: [UIView] { public var fromViews: [UIView] {
var views: [UIView] = 0 < fromViewController.view.motionTransitionIdentifier.utf16.count ? [fromViewController.view] : [] var views: [UIView] = []
subviews(of: fromViewController.view, views: &views) subviews(of: fromViewController.view, views: &views)
return views return views
} }
...@@ -272,40 +309,6 @@ extension MotionTransitionDelegate { ...@@ -272,40 +309,6 @@ extension MotionTransitionDelegate {
subviews(of: v, views: &views) subviews(of: v, views: &views)
} }
} }
fileprivate func snapshotView(for view: UIView) -> UIView {
view.isHidden = false
// capture a snapshot without cornerRadius
let oldCornerRadius = view.cornerRadius
view.cornerRadius = 0
let v = view.snapshotView(afterScreenUpdates: false)!
view.cornerRadius = oldCornerRadius
let contentView = v.subviews.first!
contentView.cornerRadius = view.cornerRadius
contentView.masksToBounds = true
v.motionTransitionIdentifier = view.motionTransitionIdentifier
v.cornerRadius = view.cornerRadius
v.zPosition = view.zPosition
v.opacity = view.opacity
v.isOpaque = view.isOpaque
v.anchorPoint = view.anchorPoint
v.layer.masksToBounds = view.layer.masksToBounds
v.borderColor = view.borderColor
v.borderWidth = view.borderWidth
v.shadowRadius = view.shadowRadius
v.shadowOpacity = view.shadowOpacity
v.shadowColor = view.shadowColor
v.shadowOffset = view.shadowOffset
v.layer.transform = view.layer.transform
view.isHidden = true
return v
}
} }
open class MotionTransitionPresentedAnimator: MotionTransitionAnimator { open class MotionTransitionPresentedAnimator: MotionTransitionAnimator {
...@@ -313,6 +316,11 @@ open class MotionTransitionPresentedAnimator: MotionTransitionAnimator { ...@@ -313,6 +316,11 @@ open class MotionTransitionPresentedAnimator: MotionTransitionAnimator {
open override func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { open override func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
super.animateTransition(using: transitionContext) super.animateTransition(using: transitionContext)
let bgView = UIView()
bgView.backgroundColor = .clear
bgView.frame = transitionView.bounds
transitionView.addSubview(bgView)
for toView in toViews { for toView in toViews {
for fromView in fromViews { for fromView in fromViews {
if toView.motionTransitionIdentifier == fromView.motionTransitionIdentifier { if toView.motionTransitionIdentifier == fromView.motionTransitionIdentifier {
...@@ -338,26 +346,21 @@ open class MotionTransitionPresentedAnimator: MotionTransitionAnimator { ...@@ -338,26 +346,21 @@ open class MotionTransitionPresentedAnimator: MotionTransitionAnimator {
} }
} }
// var w: CGFloat = toView.bounds.width var w: CGFloat = toView.bounds.width
// var h: CGFloat = toView.bounds.height var h: CGFloat = toView.bounds.height
// var px: CGFloat = toView.position.x + w / 2 var px: CGFloat = toView.position.x + w / 2
// var py: CGFloat = toView.position.y + h / 2 var py: CGFloat = toView.position.y + h / 2
// a.append(Motion.position(x: px, y: py)) a.append(Motion.position(x: px, y: py))
// a.append(Motion.width(w)) a.append(Motion.size(CGSize(width: w, height: h)))
// a.append(Motion.height(h))
// let rotate = Motion.rotate(angle: toView.layer.value(forKeyPath: MotionAnimationKeyPath.rotation.rawValue) as? CGFloat ?? 0) let rotate = Motion.rotate(angle: toView.layer.value(forKeyPath: MotionAnimationKeyPath.rotation.rawValue) as? CGFloat ?? 0)
// rotate.fromValue = fromView.layer.value(forKeyPath: MotionAnimationKeyPath.rotation.rawValue) rotate.fromValue = fromView.layer.value(forKeyPath: MotionAnimationKeyPath.rotation.rawValue)
// a.append(rotate) a.append(rotate)
a.append(Motion.background(color: toView.backgroundColor ?? .clear)) a.append(Motion.background(color: toView.backgroundColor ?? .clear))
// a.append(Motion.corner(radius: toView.cornerRadius)) a.append(Motion.corner(radius: toView.cornerRadius))
let snapshot = snapshotView(for: fromView) let snapshot = transitionView.snapshot(view: fromView, afterUpdates: true)
snapshot.isHidden = false
snapshot.bounds = fromView.bounds
snapshot.position = fromView.superview?.convert(fromView.position, to: nil) ?? fromView.position
transitionView.addSubview(snapshot)
Motion.delay(t) { Motion.delay(t) {
for ta in toView.motionTransitionAnimations { for ta in toView.motionTransitionAnimations {
...@@ -376,12 +379,19 @@ open class MotionTransitionPresentedAnimator: MotionTransitionAnimator { ...@@ -376,12 +379,19 @@ open class MotionTransitionPresentedAnimator: MotionTransitionAnimator {
g.timingFunction = MotionAnimationTimingFunctionToValue(timingFunction: tf) g.timingFunction = MotionAnimationTimingFunctionToValue(timingFunction: tf)
snapshot.animate(g) snapshot.animate(g)
snapshot.subviews.first!.animate(g)
} }
} }
} }
} }
Motion.delay(transitionDuration(using: transitionContext)) { [weak self] in let d = transitionDuration(using: transitionContext)
if let v = toViewController.view.backgroundColor {
bgView.motion(.backgroundColor(v), .duration(d))
}
Motion.delay(d) { [weak self] in
defer { defer {
transitionContext.completeTransition(!transitionContext.transitionWasCancelled) transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
} }
...@@ -390,8 +400,11 @@ open class MotionTransitionPresentedAnimator: MotionTransitionAnimator { ...@@ -390,8 +400,11 @@ open class MotionTransitionPresentedAnimator: MotionTransitionAnimator {
return return
} }
// s.transitionView.removeFromSuperview()
s.containerView.addSubview(s.toViewController.view) s.containerView.addSubview(s.toViewController.view)
s.transitionView.removeFromSuperview()
for v in s.transitionView.subviews {
v.removeFromSuperview()
}
} }
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment