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
92f3daab
Unverified
Commit
92f3daab
authored
Mar 30, 2017
by
Daniel Dahan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
development: refined PresentedMotion phase 1
parent
d50305a1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
22 additions
and
392 deletions
+22
-392
Sources/iOS/Material+Motion.swift
+22
-392
No files found.
Sources/iOS/Material+Motion.swift
View file @
92f3daab
...
...
@@ -344,7 +344,7 @@ public protocol MotionDelegate {
optional
func
motionDelayTransitionByTimeInterval
(
motion
:
Motion
)
->
TimeInterval
}
open
class
Motion
:
NSObject
{
open
class
Motion
Animator
:
NSObject
{
/// A boolean indicating whether Motion is presenting a view controller.
open
fileprivate
(
set
)
var
isPresenting
:
Bool
...
...
@@ -408,11 +408,6 @@ open class Motion: NSObject {
return
Motion
.
subviews
(
of
:
fromView
)
}
/// A time value to delay the transition animation by.
fileprivate
var
delayTransitionByTimeInterval
:
TimeInterval
{
return
fromViewController
.
motionDelegate
?
.
motionDelayTransitionByTimeInterval
?(
motion
:
self
)
??
0
}
/// The default initializer.
public
override
init
()
{
isPresenting
=
false
...
...
@@ -515,7 +510,7 @@ open class Motion: NSObject {
}
}
extension
Motion
:
UIViewControllerAnimatedTransitioning
{
extension
Motion
Animator
:
UIViewControllerAnimatedTransitioning
{
/**
The animation method that is used to coordinate the transition.
- Parameter using transitionContext: A UIViewControllerContextTransitioning.
...
...
@@ -523,21 +518,6 @@ extension Motion: UIViewControllerAnimatedTransitioning {
@objc(animateTransition:)
open
func
animateTransition
(
using
transitionContext
:
UIViewControllerContextTransitioning
)
{
self
.
transitionContext
=
transitionContext
fromViewController
.
motionDelegate
?
.
motion
?(
motion
:
self
,
willTransition
:
fromView
,
toView
:
toView
)
Motion
.
delay
(
delayTransitionByTimeInterval
)
{
[
weak
self
]
in
guard
let
s
=
self
else
{
return
}
s
.
prepareContainerView
()
s
.
prepareTransitionSnapshot
()
s
.
prepareTransitionPairs
()
s
.
prepareTransitionView
()
s
.
prepareTransitionBackgroundView
()
s
.
prepareToView
()
s
.
prepareTransitionAnimation
()
}
}
/**
...
...
@@ -551,66 +531,7 @@ extension Motion: UIViewControllerAnimatedTransitioning {
}
}
extension
Motion
{
/// Prepares the containerView.
fileprivate
func
prepareContainerView
()
{
containerView
=
transitionContext
.
containerView
}
/// Prepares the transitionSnapshot.
fileprivate
func
prepareTransitionSnapshot
()
{
transitionSnapshot
=
fromView
.
transitionSnapshot
(
afterUpdates
:
true
,
shouldHide
:
false
)
transitionSnapshot
.
frame
=
fromView
.
frame
containerView
.
addSubview
(
transitionSnapshot
)
}
/// Prepares the transitionPairs.
fileprivate
func
prepareTransitionPairs
()
{
for
from
in
fromSubviews
{
for
to
in
toSubviews
{
guard
to
.
motionIdentifier
==
from
.
motionIdentifier
else
{
continue
}
transitionPairs
.
append
((
from
,
to
))
}
}
}
/// Prepares the transitionView.
fileprivate
func
prepareTransitionView
()
{
transitionView
.
frame
=
toView
.
bounds
transitionView
.
isUserInteractionEnabled
=
false
containerView
.
insertSubview
(
transitionView
,
belowSubview
:
transitionSnapshot
)
}
/// Prepares the transitionBackgroundView.
fileprivate
func
prepareTransitionBackgroundView
()
{
transitionBackgroundView
.
backgroundColor
=
isPresenting
?
.
clear
:
fromView
.
backgroundColor
??
.
clear
transitionBackgroundView
.
frame
=
transitionView
.
bounds
transitionView
.
addSubview
(
transitionBackgroundView
)
}
/// Prepares the toView.
fileprivate
func
prepareToView
()
{
toView
.
isHidden
=
isPresenting
containerView
.
insertSubview
(
toView
,
belowSubview
:
transitionView
)
toView
.
frame
=
fromView
.
frame
toView
.
updateConstraints
()
toView
.
setNeedsLayout
()
toView
.
layoutIfNeeded
()
}
/// Prepares the transition animation.
fileprivate
func
prepareTransitionAnimation
()
{
addTransitionAnimations
()
addBackgroundAnimation
()
cleanUpAnimation
()
removeTransitionSnapshot
()
}
}
extension
Motion
{
extension
MotionAnimator
{
/// Adds the available transition animations.
fileprivate
func
addTransitionAnimations
()
{
for
(
from
,
to
)
in
transitionPairs
{
...
...
@@ -686,26 +607,7 @@ extension Motion {
}
}
extension
Motion
{
/**
Creates a CAAnimationGroup.
- Parameter animations: An Array of CAAnimation objects.
- Parameter timingFunction: An MotionAnimationTimingFunction value.
- Parameter duration: An animation duration time for the group.
- Returns: A CAAnimationGroup.
*/
open
class
func
animate
(
group
animations
:
[
CAAnimation
],
timingFunction
:
MotionAnimationTimingFunction
=
.
easeInEaseOut
,
duration
:
CFTimeInterval
=
0.5
)
->
CAAnimationGroup
{
let
group
=
CAAnimationGroup
()
group
.
fillMode
=
MotionAnimationFillModeToValue
(
mode
:
.
forwards
)
group
.
isRemovedOnCompletion
=
false
group
.
animations
=
animations
group
.
duration
=
duration
group
.
timingFunction
=
MotionAnimationTimingFunctionToValue
(
timingFunction
:
timingFunction
)
return
group
}
}
extension
Motion
{
extension
MotionAnimator
{
/**
Calculates the animation delay time based on the given Array of MotionAnimations.
- Parameter animations: An Array of MotionAnimations.
...
...
@@ -764,126 +666,20 @@ extension Motion {
}
}
extension
Motion
{
/// Cleans up the animation transition.
fileprivate
func
cleanUpAnimation
()
{
Motion
.
delay
(
transitionDuration
(
using
:
transitionContext
)
+
delayTransitionByTimeInterval
)
{
[
weak
self
]
in
guard
let
s
=
self
else
{
return
}
s
.
showToSubviews
()
s
.
removeTransitionView
()
s
.
clearTransitionPairs
()
s
.
completeTransition
()
}
}
/// Removes the transitionSnapshot from its superview.
fileprivate
func
removeTransitionSnapshot
()
{
Motion
.
delay
(
delay
)
{
[
weak
self
]
in
self
?
.
transitionSnapshot
.
removeFromSuperview
()
}
}
/// Shows the toView and its subviews.
fileprivate
func
showToSubviews
()
{
toSubviews
.
forEach
{
$0
.
isHidden
=
false
}
toView
.
isHidden
=
false
}
/// Clears the transitionPairs Array.
fileprivate
func
clearTransitionPairs
()
{
transitionPairs
.
removeAll
()
}
/// Removes the transitionView.
fileprivate
func
removeTransitionView
()
{
transitionView
.
removeFromSuperview
()
}
/// Calls the completionTransition method.
fileprivate
func
completeTransition
()
{
toViewController
.
motionDelegate
?
.
motion
?(
motion
:
self
,
didTransition
:
fromView
,
toView
:
toView
)
transitionContext
.
completeTransition
(
!
transitionContext
.
transitionWasCancelled
)
}
}
open
class
PresentedMotion
:
NSObject
{
/**
An Array of UIView pairs with common motionIdentifiers in
the from and to view controllers.
*/
open
fileprivate
(
set
)
var
transitionPairs
=
[(
UIView
,
UIView
)]()
/// A reference to the transition snapshot.
open
var
transitionSnapshot
:
UIView
!
/// A reference to the transition background view.
open
let
transitionBackgroundView
=
UIView
()
/// A reference to the view controller that is being transitioned to.
open
var
toViewController
:
UIViewController
{
return
transitionContext
.
viewController
(
forKey
:
.
to
)
!
}
/// A reference to the view controller that is being transitioned from.
open
var
fromViewController
:
UIViewController
{
return
transitionContext
.
viewController
(
forKey
:
.
from
)
!
}
/// The transition context for the current transition.
open
var
transitionContext
:
UIViewControllerContextTransitioning
!
/// The transition delay time.
open
var
delay
:
TimeInterval
=
0
/// The transition duration time.
open
var
duration
:
TimeInterval
=
0.35
/// The transition container view.
open
var
containerView
:
UIView
!
/// The view that is used to animate the transitions between view controllers.
open
var
transitionView
=
UIView
()
/// The view that is being transitioned to.
open
var
toView
:
UIView
{
return
toViewController
.
view
}
/// The subviews of the view being transitioned to.
open
var
toSubviews
:
[
UIView
]
{
return
Motion
.
subviews
(
of
:
toView
)
}
/// The view that is being transitioned from.
open
var
fromView
:
UIView
{
return
fromViewController
.
view
}
/// The subviews of the view being transitioned from.
open
var
fromSubviews
:
[
UIView
]
{
return
Motion
.
subviews
(
of
:
fromView
)
}
open
class
Motion
:
MotionAnimator
{
/// A time value to delay the transition animation by.
fileprivate
var
delayTransitionByTimeInterval
:
TimeInterval
{
return
0
// return fromViewController.motionDelegate?.motionDelayTransitionByTimeInterval?(motion: self) ?? 0
return
fromViewController
.
motionDelegate
?
.
motionDelayTransitionByTimeInterval
?(
motion
:
self
)
??
0
}
}
extension
PresentedMotion
:
UIViewControllerAnimatedTransitioning
{
/**
The animation method that is used to coordinate the transition.
- Parameter using transitionContext: A UIViewControllerContextTransitioning.
*/
@objc(animateTransition:)
open
func
animateTransition
(
using
transitionContext
:
UIViewControllerContextTransitioning
)
{
self
.
transitionContext
=
transitionContext
open
override
func
animateTransition
(
using
transitionContext
:
UIViewControllerContextTransitioning
)
{
super
.
animateTransition
(
using
:
transitionContext
)
fromViewController
.
motionDelegate
?
.
motion
?(
motion
:
self
,
willTransition
:
fromView
,
toView
:
toView
)
Motion
.
delay
(
delayTransitionByTimeInterval
)
{
[
weak
self
]
in
guard
let
s
=
self
else
{
...
...
@@ -899,19 +695,9 @@ extension PresentedMotion: UIViewControllerAnimatedTransitioning {
s
.
prepareTransitionAnimation
()
}
}
/**
Returns the transition duration time interval.
- Parameter using transitionContext: An optional UIViewControllerContextTransitioning.
- Returns: A TimeInterval that is the total animation time including delays.
*/
@objc(transitionDuration:)
open
func
transitionDuration
(
using
transitionContext
:
UIViewControllerContextTransitioning
?)
->
TimeInterval
{
return
0.35
}
}
extension
Presented
Motion
{
extension
Motion
{
/// Prepares the containerView.
fileprivate
func
prepareContainerView
()
{
containerView
=
transitionContext
.
containerView
...
...
@@ -945,15 +731,14 @@ extension PresentedMotion {
/// Prepares the transitionBackgroundView.
fileprivate
func
prepareTransitionBackgroundView
()
{
transitionBackgroundView
.
backgroundColor
=
.
clear
transitionBackgroundView
.
backgroundColor
=
isPresenting
?
.
clear
:
fromView
.
backgroundColor
??
.
clear
transitionBackgroundView
.
frame
=
transitionView
.
bounds
transitionView
.
addSubview
(
transitionBackgroundView
)
}
/// Prepares the toView.
fileprivate
func
prepareToView
()
{
toView
.
isHidden
=
true
toView
.
isHidden
=
isPresenting
containerView
.
insertSubview
(
toView
,
belowSubview
:
transitionView
)
toView
.
frame
=
fromView
.
frame
...
...
@@ -971,83 +756,7 @@ extension PresentedMotion {
}
}
extension
PresentedMotion
{
/// Adds the available transition animations.
fileprivate
func
addTransitionAnimations
()
{
for
(
from
,
to
)
in
transitionPairs
{
var
snapshotAnimations
=
[
CABasicAnimation
]()
var
snapshotChildAnimations
=
[
CABasicAnimation
]()
let
sizeAnimation
=
Motion
.
size
(
to
.
bounds
.
size
)
let
cornerRadiusAnimation
=
Motion
.
corner
(
radius
:
to
.
layer
.
cornerRadius
)
snapshotAnimations
.
append
(
sizeAnimation
)
snapshotAnimations
.
append
(
cornerRadiusAnimation
)
snapshotAnimations
.
append
(
Motion
.
position
(
to
:
to
.
motionPosition
))
snapshotAnimations
.
append
(
Motion
.
transform
(
transform
:
to
.
motionTransform
))
snapshotAnimations
.
append
(
Motion
.
background
(
color
:
to
.
backgroundColor
??
.
clear
))
if
let
path
=
to
.
layer
.
shadowPath
{
let
shadowPath
=
Motion
.
shadow
(
path
:
path
)
shadowPath
.
fromValue
=
fromView
.
layer
.
shadowPath
snapshotAnimations
.
append
(
shadowPath
)
}
let
shadowOffset
=
Motion
.
shadow
(
offset
:
to
.
layer
.
shadowOffset
)
shadowOffset
.
fromValue
=
fromView
.
layer
.
shadowOffset
snapshotAnimations
.
append
(
shadowOffset
)
let
shadowOpacity
=
Motion
.
shadow
(
opacity
:
to
.
layer
.
shadowOpacity
)
shadowOpacity
.
fromValue
=
fromView
.
layer
.
shadowOpacity
snapshotAnimations
.
append
(
shadowOpacity
)
let
shadowRadius
=
Motion
.
shadow
(
radius
:
to
.
layer
.
shadowRadius
)
shadowRadius
.
fromValue
=
fromView
.
layer
.
shadowRadius
snapshotAnimations
.
append
(
shadowRadius
)
snapshotChildAnimations
.
append
(
cornerRadiusAnimation
)
snapshotChildAnimations
.
append
(
sizeAnimation
)
snapshotChildAnimations
.
append
(
Motion
.
position
(
x
:
to
.
bounds
.
width
/
2
,
y
:
to
.
bounds
.
height
/
2
))
let
d
=
calculateAnimationTransitionDuration
(
animations
:
to
.
motionAnimations
)
let
snapshot
=
from
.
transitionSnapshot
(
afterUpdates
:
true
)
transitionView
.
addSubview
(
snapshot
)
Motion
.
delay
(
calculateAnimationDelayTimeInterval
(
animations
:
to
.
motionAnimations
))
{
[
weak
self
,
weak
to
]
in
guard
let
s
=
self
else
{
return
}
guard
let
v
=
to
else
{
return
}
let
tf
=
s
.
calculateAnimationTimingFunction
(
animations
:
v
.
motionAnimations
)
let
snapshotGroup
=
Motion
.
animate
(
group
:
snapshotAnimations
,
duration
:
d
)
snapshotGroup
.
fillMode
=
MotionAnimationFillModeToValue
(
mode
:
.
forwards
)
snapshotGroup
.
isRemovedOnCompletion
=
false
snapshotGroup
.
timingFunction
=
MotionAnimationTimingFunctionToValue
(
timingFunction
:
tf
)
let
snapshotChildGroup
=
Motion
.
animate
(
group
:
snapshotChildAnimations
,
duration
:
d
)
snapshotChildGroup
.
fillMode
=
MotionAnimationFillModeToValue
(
mode
:
.
forwards
)
snapshotChildGroup
.
isRemovedOnCompletion
=
false
snapshotChildGroup
.
timingFunction
=
MotionAnimationTimingFunctionToValue
(
timingFunction
:
tf
)
snapshot
.
animate
(
snapshotGroup
)
snapshot
.
subviews
.
first
?
.
animate
(
snapshotChildGroup
)
}
}
}
/// Adds the background animation.
fileprivate
func
addBackgroundAnimation
()
{
transitionBackgroundView
.
motion
(
.
backgroundColor
(
toView
.
backgroundColor
??
.
clear
),
.
duration
(
transitionDuration
(
using
:
transitionContext
)))
}
}
extension
PresentedMotion
{
extension
Motion
{
/**
Creates a CAAnimationGroup.
- Parameter animations: An Array of CAAnimation objects.
...
...
@@ -1066,66 +775,7 @@ extension PresentedMotion {
}
}
extension
PresentedMotion
{
/**
Calculates the animation delay time based on the given Array of MotionAnimations.
- Parameter animations: An Array of MotionAnimations.
- Returns: A TimeInterval.
*/
fileprivate
func
calculateAnimationDelayTimeInterval
(
animations
:
[
MotionAnimation
])
->
TimeInterval
{
var
t
:
TimeInterval
=
0
for
a
in
animations
{
switch
a
{
case
let
.
delay
(
time
):
if
time
>
delay
{
delay
=
time
}
t
=
time
default
:
break
}
}
return
t
}
/**
Calculates the animation transition duration based on the given Array of MotionAnimations.
- Parameter animations: An Array of MotionAnimations.
- Returns: A TimeInterval.
*/
fileprivate
func
calculateAnimationTransitionDuration
(
animations
:
[
MotionAnimation
])
->
TimeInterval
{
var
t
:
TimeInterval
=
0.35
for
a
in
animations
{
switch
a
{
case
let
.
duration
(
time
):
if
time
>
duration
{
duration
=
time
}
t
=
time
default
:
break
}
}
return
t
}
/**
Calculates the animation timing function based on the given Array of MotionAnimations.
- Parameter animations: An Array of MotionAnimations.
- Returns: A MotionAnimationTimingFunction.
*/
fileprivate
func
calculateAnimationTimingFunction
(
animations
:
[
MotionAnimation
])
->
MotionAnimationTimingFunction
{
var
t
=
MotionAnimationTimingFunction
.
easeInEaseOut
for
a
in
animations
{
switch
a
{
case
let
.
timingFunction
(
timingFunction
):
t
=
timingFunction
default
:
break
}
}
return
t
}
}
extension
PresentedMotion
{
extension
Motion
{
/// Cleans up the animation transition.
fileprivate
func
cleanUpAnimation
()
{
Motion
.
delay
(
transitionDuration
(
using
:
transitionContext
)
+
delayTransitionByTimeInterval
)
{
[
weak
self
]
in
...
...
@@ -1167,11 +817,13 @@ extension PresentedMotion {
/// Calls the completionTransition method.
fileprivate
func
completeTransition
()
{
//
toViewController.motionDelegate?.motion?(motion: self, didTransition: fromView, toView: toView)
toViewController
.
motionDelegate
?
.
motion
?(
motion
:
self
,
didTransition
:
fromView
,
toView
:
toView
)
transitionContext
.
completeTransition
(
!
transitionContext
.
transitionWasCancelled
)
}
}
open
class
PresentedMotion
:
Motion
{}
open
class
DismissedMotion
:
NSObject
{
/**
An Array of UIView pairs with common motionIdentifiers in
...
...
@@ -1314,13 +966,10 @@ extension DismissedMotion {
/// Prepares the toView.
fileprivate
func
prepareToView
()
{
toView
.
isHidden
=
true
// containerView.insertSubview(toView, belowSubview: transitionView)
//
// toView.frame = fromView.frame
// toView.updateConstraints()
// toView.setNeedsLayout()
// toView.layoutIfNeeded()
toView
.
frame
=
fromView
.
frame
toView
.
updateConstraints
()
toView
.
setNeedsLayout
()
toView
.
layoutIfNeeded
()
}
/// Prepares the transition animation.
...
...
@@ -1410,25 +1059,6 @@ extension DismissedMotion {
extension
DismissedMotion
{
/**
Creates a CAAnimationGroup.
- Parameter animations: An Array of CAAnimation objects.
- Parameter timingFunction: An MotionAnimationTimingFunction value.
- Parameter duration: An animation duration time for the group.
- Returns: A CAAnimationGroup.
*/
open
class
func
animate
(
group
animations
:
[
CAAnimation
],
timingFunction
:
MotionAnimationTimingFunction
=
.
easeInEaseOut
,
duration
:
CFTimeInterval
=
0.5
)
->
CAAnimationGroup
{
let
group
=
CAAnimationGroup
()
group
.
fillMode
=
MotionAnimationFillModeToValue
(
mode
:
.
forwards
)
group
.
isRemovedOnCompletion
=
false
group
.
animations
=
animations
group
.
duration
=
duration
group
.
timingFunction
=
MotionAnimationTimingFunctionToValue
(
timingFunction
:
timingFunction
)
return
group
}
}
extension
DismissedMotion
{
/**
Calculates the animation delay time based on the given Array of MotionAnimations.
- Parameter animations: An Array of MotionAnimations.
- Returns: A TimeInterval.
...
...
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