Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
Material
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Dmitriy Stepanets
Material
Commits
1e63fdbd
Unverified
Commit
1e63fdbd
authored
Jan 22, 2017
by
Daniel Dahan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
development: added transitionView to MotionTransition animations
parent
e46c5a84
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
280 additions
and
298 deletions
+280
-298
Sources/iOS/Material+UIView.swift
+33
-0
Sources/iOS/MotionAnimation.swift
+49
-9
Sources/iOS/MotionTransition.swift
+198
-289
No files found.
Sources/iOS/Material+UIView.swift
View file @
1e63fdbd
...
...
@@ -32,6 +32,39 @@ import UIKit
/// Grid extension for UIView.
extension
UIView
{
/// A property that accesses the backing layer's masksToBounds.
@IBInspectable
open
var
masksToBounds
:
Bool
{
get
{
return
layer
.
masksToBounds
}
set
(
value
)
{
layer
.
masksToBounds
=
value
}
}
/// A property that accesses the backing layer's opacity.
@IBInspectable
open
var
opacity
:
Float
{
get
{
return
layer
.
opacity
}
set
(
value
)
{
layer
.
opacity
=
value
}
}
/// A property that accesses the backing layer's anchorPoint.
@IBInspectable
open
var
anchorPoint
:
CGPoint
{
get
{
return
layer
.
anchorPoint
}
set
(
value
)
{
layer
.
anchorPoint
=
value
}
}
/// A property that accesses the frame.origin.x property.
@IBInspectable
open
var
x
:
CGFloat
{
...
...
Sources/iOS/MotionAnimation.swift
View file @
1e63fdbd
...
...
@@ -52,6 +52,7 @@ public enum MotionAnimationKeyPath: String {
case
zPosition
case
width
=
"bounds.size.width"
case
height
=
"bounds.size.height"
case
size
=
"bounds.size"
}
public
enum
MotionAnimation
{
...
...
@@ -87,6 +88,7 @@ public enum MotionAnimation {
case
zPosition
(
Int
)
case
width
(
CGFloat
)
case
height
(
CGFloat
)
case
size
(
CGSize
)
}
extension
CALayer
{
...
...
@@ -190,6 +192,22 @@ extension CALayer {
var
tf
=
timingFunction
var
d
=
duration
var
px
:
CGFloat
=
s
.
position
.
x
var
py
:
CGFloat
=
s
.
position
.
y
for
v
in
animations
{
switch
v
{
case
let
.
x
(
x
):
px
=
x
+
w
/
2
case
let
.
y
(
y
):
py
=
y
+
h
/
2
case
let
.
point
(
x
,
y
):
px
=
x
+
w
/
2
py
=
y
+
h
/
2
default
:
break
}
}
for
v
in
animations
{
switch
v
{
case
let
.
timingFunction
(
timingFunction
):
...
...
@@ -239,12 +257,9 @@ extension CALayer {
a
.
append
(
Motion
.
translateY
(
to
:
to
))
case
let
.
translateZ
(
to
):
a
.
append
(
Motion
.
translateZ
(
to
:
to
))
case
let
.
x
(
x
):
a
.
append
(
Motion
.
position
(
to
:
CGPoint
(
x
:
x
+
w
/
2
,
y
:
s
.
position
.
y
)))
case
let
.
y
(
y
):
a
.
append
(
Motion
.
position
(
to
:
CGPoint
(
x
:
s
.
position
.
x
,
y
:
y
+
h
/
2
)))
case
let
.
point
(
x
,
y
):
a
.
append
(
Motion
.
position
(
to
:
CGPoint
(
x
:
x
+
w
/
2
,
y
:
y
+
h
/
2
)))
case
let
.
x
(
_
),
.
y
(
_
),
.
point
(
_
,
_
):
let
position
=
Motion
.
position
(
to
:
CGPoint
(
x
:
px
,
y
:
py
))
a
.
append
(
position
)
case
let
.
position
(
x
,
y
):
a
.
append
(
Motion
.
position
(
to
:
CGPoint
(
x
:
x
,
y
:
y
)))
case
let
.
shadow
(
path
):
...
...
@@ -261,6 +276,8 @@ extension CALayer {
a
.
append
(
Motion
.
width
(
w
))
case
let
.
height
(
h
):
a
.
append
(
Motion
.
height
(
h
))
case
let
.
size
(
size
):
a
.
append
(
Motion
.
size
(
size
))
default
:
break
}
}
...
...
@@ -523,14 +540,26 @@ extension Motion {
/**
Creates a CABasicAnimation for the position key path.
- Parameter to point: A CGPoint.
- Parameter x: A CGFloat.
- Parameter y: A CGFloat.
- Returns: A CABasicAnimation.
*/
public
static
func
position
(
to
point
:
CGPoin
t
)
->
CABasicAnimation
{
public
static
func
position
(
x
:
CGFloat
,
y
:
CGFloa
t
)
->
CABasicAnimation
{
let
animation
=
CABasicAnimation
(
keyPath
:
.
position
)
animation
.
toValue
=
NSValue
(
cgPoint
:
point
)
animation
.
toValue
=
NSValue
(
cgPoint
:
CGPoint
(
x
:
x
,
y
:
y
)
)
return
animation
}
/**
Creates a CABasicAnimation for the position key path.
- Parameter to point: A CGPoint.
- Returns: A CABasicAnimation.
*/
public
static
func
position
(
to
point
:
CGPoint
)
->
CABasicAnimation
{
let
animation
=
CABasicAnimation
(
keyPath
:
.
position
)
animation
.
toValue
=
NSValue
(
cgPoint
:
point
)
return
animation
}
/**
Creates a CABasicAnimation for the shadowPath key path.
...
...
@@ -586,4 +615,15 @@ extension Motion {
animation
.
toValue
=
NSNumber
(
floatLiteral
:
Double
(
height
))
return
animation
}
/**
Creates a CABasicaAnimation for the height key path.
- Parameter size: A CGSize.
- Returns: A CABasicAnimation.
*/
public
static
func
size
(
_
size
:
CGSize
)
->
CABasicAnimation
{
let
animation
=
CABasicAnimation
(
keyPath
:
.
size
)
animation
.
toValue
=
NSValue
(
cgSize
:
size
)
return
animation
}
}
Sources/iOS/MotionTransition.swift
View file @
1e63fdbd
...
...
@@ -123,7 +123,7 @@ extension UIView {
open
class
MotionTransitionPresentationController
:
UIPresentationController
{
open
override
func
presentationTransitionWillBegin
()
{
guard
let
containerView
=
containerView
else
{
guard
nil
!
=
containerView
else
{
return
}
...
...
@@ -139,7 +139,7 @@ open class MotionTransitionPresentationController: UIPresentationController {
}
open
override
func
dismissalTransitionWillBegin
()
{
guard
let
containerView
=
containerView
else
{
guard
nil
!
=
containerView
else
{
return
}
...
...
@@ -161,62 +161,10 @@ open class MotionTransitionPresentationController: UIPresentationController {
open
class
MotionTransitionDelegate
:
NSObject
{
open
var
isPresenting
=
false
open
var
transitionContext
:
UIViewControllerContextTransitioning
!
open
var
containerView
:
UIView
!
open
var
toView
:
UIView
!
open
var
toViews
:
[
UIView
]
{
var
views
:
[
UIView
]
=
0
<
toViewController
.
view
.
motionTransitionIdentifier
.
utf16
.
count
?
[
toViewController
.
view
]
:
[]
subviews
(
of
:
toViewController
.
view
,
views
:
&
views
)
return
views
}
open
var
toViewController
:
UIViewController
!
open
var
toViewStartFrame
:
CGRect
!
open
var
toViewFinalFrame
:
CGRect
!
open
var
fromView
:
UIView
!
open
var
fromViews
:
[
UIView
]
{
var
views
:
[
UIView
]
=
0
<
fromViewController
.
view
.
motionTransitionIdentifier
.
utf16
.
count
?
[
fromViewController
.
view
]
:
[]
subviews
(
of
:
fromViewController
.
view
,
views
:
&
views
)
return
views
}
open
var
fromViewController
:
UIViewController
!
open
var
fromViewFinalFrame
:
CGRect
!
}
extension
MotionTransitionDelegate
{
@objc(animateTransition:)
open
func
animateTransition
(
using
transitionContext
:
UIViewControllerContextTransitioning
)
{
}
@objc(transitionDuration:)
open
func
transitionDuration
(
using
transitionContext
:
UIViewControllerContextTransitioning
?)
->
TimeInterval
{
return
0.25
}
open
func
animationEnded
(
_
transitionCompleted
:
Bool
)
{
// print("MotionTransitionAnimator", #function)
}
}
extension
MotionTransitionDelegate
{
fileprivate
func
subviews
(
of
view
:
UIView
,
views
:
inout
[
UIView
])
{
for
v
in
view
.
subviews
{
if
0
<
v
.
motionTransitionIdentifier
.
utf16
.
count
{
views
.
append
(
v
)
}
subviews
(
of
:
v
,
views
:
&
views
)
}
}
}
extension
MotionTransitionDelegate
:
UIViewControllerTransitioningDelegate
{
...
...
@@ -266,206 +214,115 @@ extension MotionTransitionDelegate: UITabBarControllerDelegate {
}
}
open
class
MotionTransitionInteractiveDelegate
:
UIPercentDrivenInteractiveTransition
{
open
var
isPresenting
=
false
open
class
MotionTransitionAnimator
:
MotionTransitionDelegate
{
open
var
transitionContext
:
UIViewControllerContextTransitioning
!
open
var
containerView
:
UIView
!
open
var
toView
:
UIView
!
open
var
toViewController
:
UIViewController
!
open
var
toViewStartFrame
:
CGRect
!
open
var
toViewFinalFrame
:
CGRect
!
open
var
delay
:
TimeInterval
=
0
open
var
duration
:
TimeInterval
=
0
open
var
fromView
:
UIView
!
open
var
fromViewController
:
UIViewController
!
open
var
fromViewFinalFrame
:
CGRect
!
open
var
containerView
:
UIView
!
open
var
transitionView
=
UIView
()
open
var
panGesture
:
UIPanGestureRecognizer
!
public
var
toViews
:
[
UIView
]
{
var
views
:
[
UIView
]
=
0
<
toViewController
.
view
.
motionTransitionIdentifier
.
utf16
.
count
?
[
toViewController
.
view
]
:
[]
subviews
(
of
:
toViewController
.
view
,
views
:
&
views
)
return
views
}
@objc(startInteractiveTransition:)
open
override
func
startInteractiveTransition
(
_
transitionContext
:
UIViewControllerContextTransitioning
)
{
super
.
startInteractiveTransition
(
transitionContext
)
guard
let
tView
=
transitionContext
.
view
(
forKey
:
.
to
)
else
{
return
}
public
var
fromViews
:
[
UIView
]
{
var
views
:
[
UIView
]
=
0
<
fromViewController
.
view
.
motionTransitionIdentifier
.
utf16
.
count
?
[
fromViewController
.
view
]
:
[]
subviews
(
of
:
fromViewController
.
view
,
views
:
&
views
)
return
views
}
}
extension
MotionTransitionAnimator
:
UIViewControllerAnimatedTransitioning
{
@objc(animateTransition:)
open
func
animateTransition
(
using
transitionContext
:
UIViewControllerContextTransitioning
)
{
guard
let
tVC
=
transitionContext
.
viewController
(
forKey
:
.
to
)
else
{
return
}
guard
let
fView
=
transitionContext
.
view
(
forKey
:
.
from
)
else
{
return
}
guard
let
fVC
=
transitionContext
.
viewController
(
forKey
:
.
from
)
else
{
return
}
self
.
transitionContext
=
transitionContext
containerView
=
transitionContext
.
containerView
containerView
.
addSubview
(
transitionView
)
transitionView
.
frame
=
containerView
.
bounds
toView
=
tView
toViewController
=
tVC
fromView
=
fView
fromViewController
=
fVC
toViewStartFrame
=
transitionContext
.
initialFrame
(
for
:
toViewController
)
toViewFinalFrame
=
transitionContext
.
finalFrame
(
for
:
toViewController
)
fromViewFinalFrame
=
transitionContext
.
finalFrame
(
for
:
fromViewController
)
preparePanGesture
()
}
open
func
animationEnded
(
_
transitionCompleted
:
Bool
)
{
// print("MotionTransitionAnimator", #function)
}
}
extension
MotionTransitionInteractiveDelegate
{
fileprivate
func
preparePanGesture
()
{
panGesture
=
UIPanGestureRecognizer
(
target
:
self
,
action
:
#selector(
handlePanGesture(recognizer:)
)
)
panGesture
.
maximumNumberOfTouches
=
1
containerView
.
addGestureRecognizer
(
panGesture
)
@objc(transitionDuration:)
open
func
transitionDuration
(
using
transitionContext
:
UIViewControllerContextTransitioning
?)
->
TimeInterval
{
return
delay
+
duration
}
}
extension
MotionTransitionInteractiveDelegate
{
@objc
fileprivate
func
handlePanGesture
(
recognizer
:
UIPanGestureRecognizer
)
{
switch
recognizer
.
state
{
case
.
began
:
panGesture
.
setTranslation
(
.
zero
,
in
:
containerView
)
case
.
changed
:
let
translation
=
panGesture
.
translation
(
in
:
containerView
)
/**
Compute how far the gesture recognizer tranveled on the
vertical axis.
*/
let
percentageComplete
=
fabs
(
translation
.
y
/
containerView
.
bounds
.
height
)
update
(
percentageComplete
)
case
.
ended
:
finish
()
containerView
.
removeGestureRecognizer
(
panGesture
)
default
:
break
extension
MotionTransitionDelegate
{
fileprivate
func
subviews
(
of
view
:
UIView
,
views
:
inout
[
UIView
])
{
for
v
in
view
.
subviews
{
if
0
<
v
.
motionTransitionIdentifier
.
utf16
.
count
{
views
.
append
(
v
)
}
subviews
(
of
:
v
,
views
:
&
views
)
}
}
}
open
class
MotionTransitionAnimator
:
MotionTransitionDelegate
,
UIViewControllerAnimatedTransitioning
{
@objc(animateTransition:)
open
override
func
animateTransition
(
using
transitionContext
:
UIViewControllerContextTransitioning
)
{
// guard let tView = transitionContext.view(forKey: .to) else {
// return
// }
guard
let
tVC
=
transitionContext
.
viewController
(
forKey
:
.
to
)
else
{
return
}
// guard let fView = transitionContext.view(forKey: .from) else {
// return
// }
guard
let
fVC
=
transitionContext
.
viewController
(
forKey
:
.
from
)
else
{
return
}
self
.
transitionContext
=
transitionContext
fileprivate
func
snapshotView
(
for
view
:
UIView
)
->
UIView
{
view
.
isHidden
=
false
containerView
=
transitionContext
.
containerView
// capture a snapshot without cornerRadius
let
oldCornerRadius
=
view
.
cornerRadius
view
.
cornerRadius
=
0
let
v
=
view
.
snapshotView
(
afterScreenUpdates
:
false
)
!
view
.
cornerRadius
=
oldCornerRadius
// toView = tView
toViewController
=
tVC
// fromView = fView
fromViewController
=
fVC
let
contentView
=
v
.
subviews
.
first
!
contentView
.
cornerRadius
=
view
.
cornerRadius
contentView
.
masksToBounds
=
true
toViewStartFrame
=
transitionContext
.
initialFrame
(
for
:
toViewController
)
toViewFinalFrame
=
transitionContext
.
finalFrame
(
for
:
toViewController
)
fromViewFinalFrame
=
transitionContext
.
finalFrame
(
for
:
fromViewController
)
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
ar
duration
=
transitionDuration
(
using
:
nil
)
v
.
layer
.
transform
=
view
.
layer
.
transform
transitionContext
.
containerView
.
addSubview
(
toViewController
.
view
)
view
.
isHidden
=
true
for
v
in
toViews
{
if
0
<
v
.
motionTransitionIdentifier
.
utf16
.
count
{
for
a
in
v
.
motionTransitionAnimations
{
switch
a
{
case
let
.
duration
(
dur
):
if
dur
>
duration
{
duration
=
dur
}
default
:
break
}
}
v
.
motion
(
v
.
motionTransitionAnimations
)
}
}
Motion
.
delay
(
duration
)
{
transitionContext
.
completeTransition
(
!
transitionContext
.
transitionWasCancelled
)
}
return
v
}
}
open
class
MotionTransitionPresentedAnimator
:
MotionTransition
Delegate
,
UIViewControllerAnimatedTransitioning
{
open
class
MotionTransitionPresentedAnimator
:
MotionTransition
Animator
{
@objc(animateTransition:)
open
override
func
animateTransition
(
using
transitionContext
:
UIViewControllerContextTransitioning
)
{
// guard let tView = transitionContext.view(forKey: .to) else {
// return
// }
guard
let
tVC
=
transitionContext
.
viewController
(
forKey
:
.
to
)
else
{
return
}
// guard let fView = transitionContext.view(forKey: .from) else {
// return
// }
guard
let
fVC
=
transitionContext
.
viewController
(
forKey
:
.
from
)
else
{
return
}
self
.
transitionContext
=
transitionContext
containerView
=
transitionContext
.
containerView
super
.
animateTransition
(
using
:
transitionContext
)
// toView = tView
toViewController
=
tVC
// fromView = fView
fromViewController
=
fVC
toViewStartFrame
=
transitionContext
.
initialFrame
(
for
:
toViewController
)
toViewFinalFrame
=
transitionContext
.
finalFrame
(
for
:
toViewController
)
fromViewFinalFrame
=
transitionContext
.
finalFrame
(
for
:
fromViewController
)
var
delay
:
TimeInterval
=
0
var
duration
=
transitionDuration
(
using
:
nil
)
transitionContext
.
containerView
.
addSubview
(
toViewController
.
view
)
for
v
in
toViews
{
for
v2
in
fromViews
{
if
v
.
motionTransitionIdentifier
==
v2
.
motionTransitionIdentifier
{
for
toView
in
toViews
{
for
fromView
in
fromViews
{
if
toView
.
motionTransitionIdentifier
==
fromView
.
motionTransitionIdentifier
{
var
t
:
TimeInterval
=
0
var
d
:
TimeInterval
=
0
var
a
=
[
CABasicAnimation
]()
var
tf
=
MotionAnimationTimingFunction
.
easeInEaseOut
var
w
:
CGFloat
=
0
var
h
:
CGFloat
=
0
for
ta
in
v
.
motionTransitionAnimations
{
for
ta
in
toView
.
motionTransitionAnimations
{
switch
ta
{
case
let
.
delay
(
time
):
if
time
>
delay
{
...
...
@@ -477,55 +334,38 @@ open class MotionTransitionPresentedAnimator: MotionTransitionDelegate, UIViewCo
duration
=
time
}
d
=
time
case
let
.
width
(
width
):
w
=
width
case
let
.
height
(
height
):
h
=
height
default
:
break
}
}
// var w: CGFloat = toView.bounds.width
// var h: CGFloat = toView.bounds.height
// var px: CGFloat = toView.position.x + w / 2
// var py: CGFloat = toView.position.y + h / 2
// a.append(Motion.position(x: px, y: py))
// a.append(Motion.width(w))
// a.append(Motion.height(h))
var
px
:
CGFloat
=
v
.
position
.
x
var
py
:
CGFloat
=
v
.
position
.
y
// let rotate = Motion.rotate(angle: toView.layer.value(forKeyPath: MotionAnimationKeyPath.rotation.rawValue) as? CGFloat ?? 0)
// rotate.fromValue = fromView.layer.value(forKeyPath: MotionAnimationKeyPath.rotation.rawValue)
// a.append(rotate)
for
ta
in
v
.
motionTransitionAnimations
{
switch
ta
{
case
let
.
x
(
x
):
px
=
x
+
w
/
2
case
let
.
y
(
y
):
py
=
y
+
h
/
2
case
let
.
point
(
x
,
y
):
px
=
x
+
w
/
2
py
=
y
+
h
/
2
default
:
break
}
}
a
.
append
(
Motion
.
background
(
color
:
toView
.
backgroundColor
??
.
clear
))
// a.append(Motion.corner(radius: toView.cornerRadius))
let
snapshot
=
snapshotView
(
for
:
fromView
)
snapshot
.
isHidden
=
false
snapshot
.
bounds
=
fromView
.
bounds
snapshot
.
position
=
fromView
.
superview
?
.
convert
(
fromView
.
position
,
to
:
nil
)
??
fromView
.
position
transitionView
.
addSubview
(
snapshot
)
Motion
.
delay
(
t
)
{
for
ta
in
v
.
motionTransitionAnimations
{
for
ta
in
toView
.
motionTransitionAnimations
{
switch
ta
{
case
let
.
timingFunction
(
timingFunction
):
tf
=
timingFunction
case
let
.
rotate
(
angle
):
let
rotate
=
Motion
.
rotate
(
angle
:
angle
)
let
radians
=
CGFloat
(
atan2f
(
Float
(
v2
.
transform
.
b
),
Float
(
v2
.
transform
.
a
)))
rotate
.
fromValue
=
v2
.
layer
.
value
(
forKeyPath
:
MotionAnimationKeyPath
.
rotation
.
rawValue
)
a
.
append
(
rotate
)
case
let
.
backgroundColor
(
color
):
a
.
append
(
Motion
.
background
(
color
:
color
))
case
let
.
corners
(
radius
):
a
.
append
(
Motion
.
corner
(
radius
:
radius
))
case
let
.
x
(
_
),
.
y
(
_
),
.
point
(
_
,
_
):
a
.
append
(
Motion
.
position
(
to
:
CGPoint
(
x
:
px
,
y
:
py
)))
case
let
.
position
(
x
,
y
):
a
.
append
(
Motion
.
position
(
to
:
CGPoint
(
x
:
x
,
y
:
y
)))
case
let
.
shadow
(
path
):
a
.
append
(
Motion
.
shadow
(
path
:
path
))
case
let
.
width
(
w
):
a
.
append
(
Motion
.
width
(
w
))
case
let
.
height
(
h
):
a
.
append
(
Motion
.
height
(
h
))
default
:
break
}
}
...
...
@@ -535,53 +375,31 @@ open class MotionTransitionPresentedAnimator: MotionTransitionDelegate, UIViewCo
g
.
isRemovedOnCompletion
=
false
g
.
timingFunction
=
MotionAnimationTimingFunctionToValue
(
timingFunction
:
tf
)
v
.
animate
(
g
)
snapshot
.
animate
(
g
)
}
}
}
}
Motion
.
delay
(
delay
+
duration
)
{
transitionContext
.
completeTransition
(
!
transitionContext
.
transitionWasCancelled
)
Motion
.
delay
(
transitionDuration
(
using
:
transitionContext
))
{
[
weak
self
]
in
defer
{
transitionContext
.
completeTransition
(
!
transitionContext
.
transitionWasCancelled
)
}
guard
let
s
=
self
else
{
return
}
// s.transitionView.removeFromSuperview()
s
.
containerView
.
addSubview
(
s
.
toViewController
.
view
)
}
}
}
open
class
MotionTransitionDismissedAnimator
:
MotionTransition
Delegate
,
UIViewControllerAnimatedTransitioning
{
open
class
MotionTransitionDismissedAnimator
:
MotionTransition
Animator
{
@objc(animateTransition:)
open
override
func
animateTransition
(
using
transitionContext
:
UIViewControllerContextTransitioning
)
{
// guard let tView = transitionContext.view(forKey: .to) else {
// return
// }
guard
let
tVC
=
transitionContext
.
viewController
(
forKey
:
.
to
)
else
{
return
}
// guard let fView = transitionContext.view(forKey: .from) else {
// return
// }
guard
let
fVC
=
transitionContext
.
viewController
(
forKey
:
.
from
)
else
{
return
}
self
.
transitionContext
=
transitionContext
containerView
=
transitionContext
.
containerView
// toView = tView
toViewController
=
tVC
// fromView = fView
fromViewController
=
fVC
toViewStartFrame
=
transitionContext
.
initialFrame
(
for
:
toViewController
)
toViewFinalFrame
=
transitionContext
.
finalFrame
(
for
:
toViewController
)
fromViewFinalFrame
=
transitionContext
.
finalFrame
(
for
:
fromViewController
)
var
delay
:
TimeInterval
=
0
var
duration
=
transitionDuration
(
using
:
nil
)
super
.
animateTransition
(
using
:
transitionContext
)
for
v
in
fromViews
{
for
v2
in
toViews
{
...
...
@@ -606,22 +424,22 @@ open class MotionTransitionDismissedAnimator: MotionTransitionDelegate, UIViewCo
d
=
time
case
let
.
timingFunction
(
timingFunction
):
tf
=
timingFunction
case
let
.
rotate
(
angle
):
case
.
rotate
(
_
):
let
radians
=
CGFloat
(
atan2f
(
Float
(
v2
.
transform
.
b
),
Float
(
v2
.
transform
.
a
)))
let
rotate
=
Motion
.
rotate
(
angle
:
radians
*
180
/
CGFloat
(
M_PI
))
rotate
.
fromValue
=
v
.
layer
.
value
(
forKeyPath
:
MotionAnimationKeyPath
.
rotation
.
rawValue
)
a
.
append
(
rotate
)
case
let
.
backgroundColor
(
color
):
case
.
backgroundColor
(
_
):
a
.
append
(
Motion
.
background
(
color
:
.
clear
))
case
let
.
corners
(
radius
):
case
.
corners
(
_
):
a
.
append
(
Motion
.
corner
(
radius
:
v2
.
cornerRadius
))
case
let
.
x
(
_
),
.
y
(
_
),
.
point
(
_
,
_
),
.
position
(
_
,
_
):
case
.
x
(
_
),
.
y
(
_
),
.
point
(
_
,
_
),
.
position
(
_
,
_
):
a
.
append
(
Motion
.
position
(
to
:
nil
==
v2
.
superview
?
v2
.
position
:
v2
.
superview
!.
convert
(
v2
.
position
,
to
:
nil
)))
case
let
.
shadow
(
path
):
a
.
append
(
Motion
.
shadow
(
path
:
path
))
case
let
.
width
(
w
):
case
.
width
(
_
):
a
.
append
(
Motion
.
width
(
v2
.
bounds
.
width
))
case
let
.
height
(
h
):
case
.
height
(
_
):
a
.
append
(
Motion
.
height
(
v2
.
bounds
.
height
))
default
:
break
}
...
...
@@ -651,3 +469,94 @@ open class MotionTransitionInteractiveAnimator: MotionTransitionInteractiveDeleg
}
}
open
class
MotionTransitionInteractiveDelegate
:
UIPercentDrivenInteractiveTransition
{
open
var
isPresenting
=
false
open
var
transitionContext
:
UIViewControllerContextTransitioning
!
open
var
containerView
:
UIView
!
open
var
toView
:
UIView
!
open
var
toViewController
:
UIViewController
!
open
var
toViewStartFrame
:
CGRect
!
open
var
toViewFinalFrame
:
CGRect
!
open
var
fromView
:
UIView
!
open
var
fromViewController
:
UIViewController
!
open
var
fromViewFinalFrame
:
CGRect
!
open
var
panGesture
:
UIPanGestureRecognizer
!
@objc(startInteractiveTransition:)
open
override
func
startInteractiveTransition
(
_
transitionContext
:
UIViewControllerContextTransitioning
)
{
super
.
startInteractiveTransition
(
transitionContext
)
guard
let
tView
=
transitionContext
.
view
(
forKey
:
.
to
)
else
{
return
}
guard
let
tVC
=
transitionContext
.
viewController
(
forKey
:
.
to
)
else
{
return
}
guard
let
fView
=
transitionContext
.
view
(
forKey
:
.
from
)
else
{
return
}
guard
let
fVC
=
transitionContext
.
viewController
(
forKey
:
.
from
)
else
{
return
}
self
.
transitionContext
=
transitionContext
containerView
=
transitionContext
.
containerView
toView
=
tView
toViewController
=
tVC
fromView
=
fView
fromViewController
=
fVC
toViewStartFrame
=
transitionContext
.
initialFrame
(
for
:
toViewController
)
toViewFinalFrame
=
transitionContext
.
finalFrame
(
for
:
toViewController
)
fromViewFinalFrame
=
transitionContext
.
finalFrame
(
for
:
fromViewController
)
preparePanGesture
()
}
open
func
animationEnded
(
_
transitionCompleted
:
Bool
)
{
// print("MotionTransitionAnimator", #function)
}
}
extension
MotionTransitionInteractiveDelegate
{
fileprivate
func
preparePanGesture
()
{
panGesture
=
UIPanGestureRecognizer
(
target
:
self
,
action
:
#selector(
handlePanGesture(recognizer:)
)
)
panGesture
.
maximumNumberOfTouches
=
1
containerView
.
addGestureRecognizer
(
panGesture
)
}
}
extension
MotionTransitionInteractiveDelegate
{
@objc
fileprivate
func
handlePanGesture
(
recognizer
:
UIPanGestureRecognizer
)
{
switch
recognizer
.
state
{
case
.
began
:
panGesture
.
setTranslation
(
.
zero
,
in
:
containerView
)
case
.
changed
:
let
translation
=
panGesture
.
translation
(
in
:
containerView
)
/**
Compute how far the gesture recognizer tranveled on the
vertical axis.
*/
let
percentageComplete
=
fabs
(
translation
.
y
/
containerView
.
bounds
.
height
)
update
(
percentageComplete
)
case
.
ended
:
finish
()
containerView
.
removeGestureRecognizer
(
panGesture
)
default
:
break
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment