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
cb8adf42
Unverified
Commit
cb8adf42
authored
Feb 03, 2017
by
Daniel Dahan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
development: added new Motion for Material 2.5.0
parent
b77365ad
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
680 additions
and
787 deletions
+680
-787
Material.xcodeproj/project.pbxproj
+0
-12
Sources/iOS/KeyframeMotion.swift
+0
-75
Sources/iOS/Motion.swift
+566
-93
Sources/iOS/MotionAnimation.swift
+108
-78
Sources/iOS/MotionTransition.swift
+0
-526
Sources/iOS/NavigationBar.swift
+6
-3
No files found.
Material.xcodeproj/project.pbxproj
View file @
cb8adf42
...
@@ -51,8 +51,6 @@
...
@@ -51,8 +51,6 @@
96328B9F1E05C24E009A4C90
/* TableViewController.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96328B981E05C0CE009A4C90
/* TableViewController.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
96328B9F1E05C24E009A4C90
/* TableViewController.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96328B981E05C0CE009A4C90
/* TableViewController.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
96334EF61C8B84660083986B
/* Assets.xcassets in Resources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96334EF51C8B84660083986B
/* Assets.xcassets */
;
};
96334EF61C8B84660083986B
/* Assets.xcassets in Resources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96334EF51C8B84660083986B
/* Assets.xcassets */
;
};
965E80C81DD4C50600D61E4B
/* Motion.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB76D1CB40DC500C806FE
/* Motion.swift */
;
};
965E80C81DD4C50600D61E4B
/* Motion.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB76D1CB40DC500C806FE
/* Motion.swift */
;
};
965E80C91DD4C50600D61E4B
/* MotionTransition.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB78B1CB40DC500C806FE
/* MotionTransition.swift */
;
};
965E80CA1DD4C50600D61E4B
/* KeyframeMotion.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB77E1CB40DC500C806FE
/* KeyframeMotion.swift */
;
};
965E80CB1DD4C50600D61E4B
/* MotionAnimation.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96E3C39D1D3A1D0C0086A024
/* MotionAnimation.swift */
;
};
965E80CB1DD4C50600D61E4B
/* MotionAnimation.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96E3C39D1D3A1D0C0086A024
/* MotionAnimation.swift */
;
};
965E80CC1DD4C50600D61E4B
/* Bar.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB7981CB40DC500C806FE
/* Bar.swift */
;
};
965E80CC1DD4C50600D61E4B
/* Bar.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB7981CB40DC500C806FE
/* Bar.swift */
;
};
965E80CD1DD4C50600D61E4B
/* Button.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB7701CB40DC500C806FE
/* Button.swift */
;
};
965E80CD1DD4C50600D61E4B
/* Button.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB7701CB40DC500C806FE
/* Button.swift */
;
};
...
@@ -154,9 +152,7 @@
...
@@ -154,9 +152,7 @@
96BCB7FA1CB40DE900C806FE
/* Roboto-Regular.ttf in Resources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB7F11CB40DE900C806FE
/* Roboto-Regular.ttf */
;
};
96BCB7FA1CB40DE900C806FE
/* Roboto-Regular.ttf in Resources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB7F11CB40DE900C806FE
/* Roboto-Regular.ttf */
;
};
96BCB7FB1CB40DE900C806FE
/* Roboto-Thin.ttf in Resources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB7F21CB40DE900C806FE
/* Roboto-Thin.ttf */
;
};
96BCB7FB1CB40DE900C806FE
/* Roboto-Thin.ttf in Resources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB7F21CB40DE900C806FE
/* Roboto-Thin.ttf */
;
};
96BCB7FC1CB40DE900C806FE
/* Roboto-Thin.ttf in Resources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB7F21CB40DE900C806FE
/* Roboto-Thin.ttf */
;
};
96BCB7FC1CB40DE900C806FE
/* Roboto-Thin.ttf in Resources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB7F21CB40DE900C806FE
/* Roboto-Thin.ttf */
;
};
96BCB8101CB4115200C806FE
/* MotionTransition.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB78B1CB40DC500C806FE
/* MotionTransition.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
96BCB8111CB4115200C806FE
/* Motion.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB76D1CB40DC500C806FE
/* Motion.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
96BCB8111CB4115200C806FE
/* Motion.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB76D1CB40DC500C806FE
/* Motion.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
96BCB8131CB4115200C806FE
/* KeyframeMotion.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB77E1CB40DC500C806FE
/* KeyframeMotion.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
96BCB8141CB4115200C806FE
/* PulseMotion.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB7821CB40DC500C806FE
/* PulseMotion.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
96BCB8141CB4115200C806FE
/* PulseMotion.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB7821CB40DC500C806FE
/* PulseMotion.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
96BCB8151CB4115200C806FE
/* FABButton.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB75F1CB40DC500C806FE
/* FABButton.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
96BCB8151CB4115200C806FE
/* FABButton.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB75F1CB40DC500C806FE
/* FABButton.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
96BCB8161CB4115200C806FE
/* FlatButton.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB7601CB40DC500C806FE
/* FlatButton.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
96BCB8161CB4115200C806FE
/* FlatButton.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB7601CB40DC500C806FE
/* FlatButton.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
...
@@ -276,7 +272,6 @@
...
@@ -276,7 +272,6 @@
96BCB77B1CB40DC500C806FE
/* Font.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
Font.swift
;
sourceTree
=
"<group>"
;
};
96BCB77B1CB40DC500C806FE
/* Font.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
Font.swift
;
sourceTree
=
"<group>"
;
};
96BCB77C1CB40DC500C806FE
/* Gravity.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
Gravity.swift
;
sourceTree
=
"<group>"
;
};
96BCB77C1CB40DC500C806FE
/* Gravity.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
Gravity.swift
;
sourceTree
=
"<group>"
;
};
96BCB77D1CB40DC500C806FE
/* Icon.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
Icon.swift
;
sourceTree
=
"<group>"
;
};
96BCB77D1CB40DC500C806FE
/* Icon.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
Icon.swift
;
sourceTree
=
"<group>"
;
};
96BCB77E1CB40DC500C806FE
/* KeyframeMotion.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
KeyframeMotion.swift
;
sourceTree
=
"<group>"
;
};
96BCB7801CB40DC500C806FE
/* Layer.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
Layer.swift
;
sourceTree
=
"<group>"
;
};
96BCB7801CB40DC500C806FE
/* Layer.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
Layer.swift
;
sourceTree
=
"<group>"
;
};
96BCB7811CB40DC500C806FE
/* Layout.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
Layout.swift
;
sourceTree
=
"<group>"
;
};
96BCB7811CB40DC500C806FE
/* Layout.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
Layout.swift
;
sourceTree
=
"<group>"
;
};
96BCB7821CB40DC500C806FE
/* PulseMotion.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
PulseMotion.swift
;
sourceTree
=
"<group>"
;
};
96BCB7821CB40DC500C806FE
/* PulseMotion.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
PulseMotion.swift
;
sourceTree
=
"<group>"
;
};
...
@@ -286,7 +281,6 @@
...
@@ -286,7 +281,6 @@
96BCB7871CB40DC500C806FE
/* InterimSpace.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
InterimSpace.swift
;
sourceTree
=
"<group>"
;
};
96BCB7871CB40DC500C806FE
/* InterimSpace.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
InterimSpace.swift
;
sourceTree
=
"<group>"
;
};
96BCB7881CB40DC500C806FE
/* Switch.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
Switch.swift
;
sourceTree
=
"<group>"
;
};
96BCB7881CB40DC500C806FE
/* Switch.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
Switch.swift
;
sourceTree
=
"<group>"
;
};
96BCB7891CB40DC500C806FE
/* TableViewCell.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
TableViewCell.swift
;
sourceTree
=
"<group>"
;
};
96BCB7891CB40DC500C806FE
/* TableViewCell.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
TableViewCell.swift
;
sourceTree
=
"<group>"
;
};
96BCB78B1CB40DC500C806FE
/* MotionTransition.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
MotionTransition.swift
;
sourceTree
=
"<group>"
;
};
96BCB78C1CB40DC500C806FE
/* View.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
View.swift
;
sourceTree
=
"<group>"
;
};
96BCB78C1CB40DC500C806FE
/* View.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
View.swift
;
sourceTree
=
"<group>"
;
};
96BCB78E1CB40DC500C806FE
/* Menu.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
indentWidth
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
Menu.swift
;
sourceTree
=
"<group>"
;
tabWidth
=
4
;
};
96BCB78E1CB40DC500C806FE
/* Menu.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
indentWidth
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
Menu.swift
;
sourceTree
=
"<group>"
;
tabWidth
=
4
;
};
96BCB7901CB40DC500C806FE
/* NavigationBar.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
NavigationBar.swift
;
sourceTree
=
"<group>"
;
};
96BCB7901CB40DC500C806FE
/* NavigationBar.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
NavigationBar.swift
;
sourceTree
=
"<group>"
;
};
...
@@ -752,8 +746,6 @@
...
@@ -752,8 +746,6 @@
children
=
(
children
=
(
96BCB76D1CB40DC500C806FE
/* Motion.swift */
,
96BCB76D1CB40DC500C806FE
/* Motion.swift */
,
96E3C39D1D3A1D0C0086A024
/* MotionAnimation.swift */
,
96E3C39D1D3A1D0C0086A024
/* MotionAnimation.swift */
,
96BCB78B1CB40DC500C806FE
/* MotionTransition.swift */
,
96BCB77E1CB40DC500C806FE
/* KeyframeMotion.swift */
,
96BCB7821CB40DC500C806FE
/* PulseMotion.swift */
,
96BCB7821CB40DC500C806FE
/* PulseMotion.swift */
,
961730351E0E156400A9A297
/* SpringMotion.swift */
,
961730351E0E156400A9A297
/* SpringMotion.swift */
,
);
);
...
@@ -832,9 +824,7 @@
...
@@ -832,9 +824,7 @@
buildActionMask
=
2147483647
;
buildActionMask
=
2147483647
;
files
=
(
files
=
(
96D88C321C1328D800B91418
/* Material.h in Headers */
,
96D88C321C1328D800B91418
/* Material.h in Headers */
,
96BCB8101CB4115200C806FE
/* MotionTransition.swift in Headers */
,
96BCB8111CB4115200C806FE
/* Motion.swift in Headers */
,
96BCB8111CB4115200C806FE
/* Motion.swift in Headers */
,
96BCB8131CB4115200C806FE
/* KeyframeMotion.swift in Headers */
,
96BCB8141CB4115200C806FE
/* PulseMotion.swift in Headers */
,
96BCB8141CB4115200C806FE
/* PulseMotion.swift in Headers */
,
96BCB8151CB4115200C806FE
/* FABButton.swift in Headers */
,
96BCB8151CB4115200C806FE
/* FABButton.swift in Headers */
,
96BCB8161CB4115200C806FE
/* FlatButton.swift in Headers */
,
96BCB8161CB4115200C806FE
/* FlatButton.swift in Headers */
,
...
@@ -1109,8 +1099,6 @@
...
@@ -1109,8 +1099,6 @@
965E80FE1DD4D59500D61E4B
/* ToolbarController.swift in Sources */
,
965E80FE1DD4D59500D61E4B
/* ToolbarController.swift in Sources */
,
96328B971E05C0BB009A4C90
/* TableView.swift in Sources */
,
96328B971E05C0BB009A4C90
/* TableView.swift in Sources */
,
965E80C81DD4C50600D61E4B
/* Motion.swift in Sources */
,
965E80C81DD4C50600D61E4B
/* Motion.swift in Sources */
,
965E80C91DD4C50600D61E4B
/* MotionTransition.swift in Sources */
,
965E80CA1DD4C50600D61E4B
/* KeyframeMotion.swift in Sources */
,
965E80F81DD4D59500D61E4B
/* ImageCard.swift in Sources */
,
965E80F81DD4D59500D61E4B
/* ImageCard.swift in Sources */
,
96328B991E05C0CE009A4C90
/* TableViewController.swift in Sources */
,
96328B991E05C0CE009A4C90
/* TableViewController.swift in Sources */
,
965E80F91DD4D59500D61E4B
/* PresenterCard.swift in Sources */
,
965E80F91DD4D59500D61E4B
/* PresenterCard.swift in Sources */
,
...
...
Sources/iOS/KeyframeMotion.swift
deleted
100644 → 0
View file @
b77365ad
/*
* Copyright (C) 2015 - 2017, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.com>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of CosmicMind nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import
UIKit
@objc(AnimationRotationMode)
public
enum
AnimationRotationMode
:
Int
{
case
`
default
`
case
auto
case
autoReverse
}
/**
Converts an AnimationRotationMode to a corresponding CAAnimationRotate key.
- Parameter mode: An AnimationRotationMode.
- Returns: An optional CAAnimationRotate key String.
*/
public
func
AnimationRotationModeToValue
(
mode
:
AnimationRotationMode
)
->
String
?
{
switch
mode
{
case
.
default
:
return
nil
case
.
auto
:
return
kCAAnimationRotateAuto
case
.
autoReverse
:
return
kCAAnimationRotateAutoReverse
}
}
extension
Motion
{
/**
Creates a CAKeyframeAnimation.
- Parameter bezierPath: A UIBezierPath.
- Parameter mode: An AnimationRotationMode.
- Parameter duration: An animation duration time.
- Returns: A CAKeyframeAnimation.
*/
public
static
func
path
(
bezierPath
:
UIBezierPath
,
mode
:
AnimationRotationMode
=
.
auto
,
duration
:
CFTimeInterval
?
=
nil
)
->
CAKeyframeAnimation
{
let
animation
=
CAKeyframeAnimation
()
animation
.
keyPath
=
MotionAnimationKeyPath
.
position
.
rawValue
animation
.
path
=
bezierPath
.
cgPath
animation
.
rotationMode
=
AnimationRotationModeToValue
(
mode
:
mode
)
if
let
v
=
duration
{
animation
.
duration
=
v
}
return
animation
}
}
Sources/iOS/Motion.swift
View file @
cb8adf42
...
@@ -32,10 +32,10 @@ import UIKit
...
@@ -32,10 +32,10 @@ import UIKit
@objc(MotionAnimationFillMode)
@objc(MotionAnimationFillMode)
public
enum
MotionAnimationFillMode
:
Int
{
public
enum
MotionAnimationFillMode
:
Int
{
case
forwards
case
forwards
case
backwards
case
backwards
case
both
case
both
case
removed
case
removed
}
}
/**
/**
...
@@ -43,16 +43,16 @@ public enum MotionAnimationFillMode: Int {
...
@@ -43,16 +43,16 @@ public enum MotionAnimationFillMode: Int {
- Parameter mode: An MotionAnimationFillMode enum value.
- Parameter mode: An MotionAnimationFillMode enum value.
*/
*/
public
func
MotionAnimationFillModeToValue
(
mode
:
MotionAnimationFillMode
)
->
String
{
public
func
MotionAnimationFillModeToValue
(
mode
:
MotionAnimationFillMode
)
->
String
{
switch
mode
{
switch
mode
{
case
.
forwards
:
case
.
forwards
:
return
kCAFillModeForwards
return
kCAFillModeForwards
case
.
backwards
:
case
.
backwards
:
return
kCAFillModeBackwards
return
kCAFillModeBackwards
case
.
both
:
case
.
both
:
return
kCAFillModeBoth
return
kCAFillModeBoth
case
.
removed
:
case
.
removed
:
return
kCAFillModeRemoved
return
kCAFillModeRemoved
}
}
}
}
@objc(MotionAnimationTimingFunction)
@objc(MotionAnimationTimingFunction)
...
@@ -86,8 +86,276 @@ public func MotionAnimationTimingFunctionToValue(timingFunction: MotionAnimation
...
@@ -86,8 +86,276 @@ public func MotionAnimationTimingFunctionToValue(timingFunction: MotionAnimation
public
typealias
MotionDelayCancelBlock
=
(
Bool
)
->
Void
public
typealias
MotionDelayCancelBlock
=
(
Bool
)
->
Void
public
struct
Motion
{
fileprivate
var
MotionInstanceKey
:
UInt8
=
0
/**
fileprivate
var
MotionInstanceControllerKey
:
UInt8
=
0
fileprivate
struct
MotionInstance
{
fileprivate
var
identifier
:
String
fileprivate
var
animations
:
[
MotionAnimation
]
}
fileprivate
struct
MotionInstanceController
{
fileprivate
var
isEnabled
:
Bool
fileprivate
weak
var
delegate
:
MotionDelegate
?
}
extension
UIViewController
:
MotionDelegate
,
UIViewControllerTransitioningDelegate
{
/// MotionInstanceController Reference.
fileprivate
var
motionInstanceController
:
MotionInstanceController
{
get
{
return
AssociatedObject
(
base
:
self
,
key
:
&
MotionInstanceControllerKey
)
{
return
MotionInstanceController
(
isEnabled
:
false
,
delegate
:
nil
)
}
}
set
(
value
)
{
AssociateObject
(
base
:
self
,
key
:
&
MotionInstanceControllerKey
,
value
:
value
)
}
}
open
var
isMotionEnabled
:
Bool
{
get
{
return
motionInstanceController
.
isEnabled
}
set
(
value
)
{
if
value
{
modalPresentationStyle
=
.
custom
transitioningDelegate
=
self
motionDelegate
=
self
}
motionInstanceController
.
isEnabled
=
value
}
}
open
weak
var
motionDelegate
:
MotionDelegate
?
{
get
{
return
motionInstanceController
.
delegate
}
set
(
value
)
{
motionInstanceController
.
delegate
=
value
}
}
}
extension
UIViewController
{
open
func
animationController
(
forPresented
presented
:
UIViewController
,
presenting
:
UIViewController
,
source
:
UIViewController
)
->
UIViewControllerAnimatedTransitioning
?
{
return
isMotionEnabled
?
Motion
(
isPresenting
:
true
)
:
nil
}
open
func
animationController
(
forDismissed
dismissed
:
UIViewController
)
->
UIViewControllerAnimatedTransitioning
?
{
return
isMotionEnabled
?
Motion
()
:
nil
}
open
func
presentationController
(
forPresented
presented
:
UIViewController
,
presenting
:
UIViewController
?,
source
:
UIViewController
)
->
UIPresentationController
?
{
return
isMotionEnabled
?
MotionPresentationController
(
presentedViewController
:
presented
,
presenting
:
presenting
)
:
nil
}
}
extension
UIView
{
/// MaterialTransitionItem Reference.
fileprivate
var
motionInstance
:
MotionInstance
{
get
{
return
AssociatedObject
(
base
:
self
,
key
:
&
MotionInstanceKey
)
{
return
MotionInstance
(
identifier
:
""
,
animations
:
[])
}
}
set
(
value
)
{
AssociateObject
(
base
:
self
,
key
:
&
MotionInstanceKey
,
value
:
value
)
}
}
open
var
motionIdentifier
:
String
{
get
{
return
motionInstance
.
identifier
}
set
(
value
)
{
motionInstance
.
identifier
=
value
}
}
open
var
motionAnimations
:
[
MotionAnimation
]
{
get
{
return
motionInstance
.
animations
}
set
(
value
)
{
motionInstance
.
animations
=
value
}
}
open
func
transitionSnapshot
(
afterUpdates
:
Bool
,
shouldHide
:
Bool
=
true
)
->
UIView
{
isHidden
=
false
let
oldCornerRadius
=
cornerRadius
cornerRadius
=
0
var
oldBackgroundColor
:
UIColor
?
if
shouldHide
{
oldBackgroundColor
=
backgroundColor
backgroundColor
=
.
clear
}
let
oldTransform
=
motionTransform
motionTransform
=
CATransform3DIdentity
let
v
=
snapshotView
(
afterScreenUpdates
:
afterUpdates
)
!
cornerRadius
=
oldCornerRadius
if
shouldHide
{
backgroundColor
=
oldBackgroundColor
}
motionTransform
=
oldTransform
let
contentView
=
v
.
subviews
.
first
!
contentView
.
cornerRadius
=
cornerRadius
contentView
.
masksToBounds
=
true
v
.
motionIdentifier
=
motionIdentifier
v
.
position
=
motionPosition
v
.
bounds
=
bounds
v
.
cornerRadius
=
cornerRadius
v
.
zPosition
=
zPosition
v
.
opacity
=
opacity
v
.
isOpaque
=
isOpaque
v
.
anchorPoint
=
anchorPoint
v
.
masksToBounds
=
masksToBounds
v
.
borderColor
=
borderColor
v
.
borderWidth
=
borderWidth
v
.
shadowRadius
=
shadowRadius
v
.
shadowOpacity
=
shadowOpacity
v
.
shadowColor
=
shadowColor
v
.
shadowOffset
=
shadowOffset
v
.
contentMode
=
contentMode
v
.
motionTransform
=
motionTransform
v
.
backgroundColor
=
backgroundColor
isHidden
=
shouldHide
return
v
}
}
open
class
MotionPresentationController
:
UIPresentationController
{
open
override
func
presentationTransitionWillBegin
()
{
guard
nil
!=
containerView
else
{
return
}
presentedViewController
.
transitionCoordinator
?
.
animate
(
alongsideTransition
:
{
(
context
)
in
print
(
"Animating"
)
})
print
(
"presentationTransitionWillBegin"
)
}
open
override
func
presentationTransitionDidEnd
(
_
completed
:
Bool
)
{
print
(
"presentationTransitionDidEnd"
)
}
open
override
func
dismissalTransitionWillBegin
()
{
guard
nil
!=
containerView
else
{
return
}
presentedViewController
.
transitionCoordinator
?
.
animate
(
alongsideTransition
:
{
(
context
)
in
print
(
"Animating"
)
})
print
(
"dismissalTransitionWillBegin"
)
}
open
override
func
dismissalTransitionDidEnd
(
_
completed
:
Bool
)
{
print
(
"dismissalTransitionDidEnd"
)
}
open
override
var
frameOfPresentedViewInContainerView
:
CGRect
{
return
containerView
?
.
bounds
??
.
zero
}
}
@objc(MotionDelegate)
public
protocol
MotionDelegate
{
@objc
optional
func
motion
(
motion
:
Motion
,
willTransition
fromView
:
UIView
,
toView
:
UIView
)
@objc
optional
func
motion
(
motion
:
Motion
,
didTransition
fromView
:
UIView
,
toView
:
UIView
)
@objc
optional
func
motionModifyDelay
(
motion
:
Motion
)
->
TimeInterval
@objc
optional
func
motionTransitionAnimation
(
motion
:
Motion
)
}
open
class
Motion
:
NSObject
{
open
var
isPresenting
:
Bool
open
fileprivate
(
set
)
var
transitionPairs
=
[(
UIView
,
UIView
)]()
open
var
transitionSnapshot
:
UIView
!
open
let
transitionBackgroundView
=
UIView
()
open
var
toViewController
:
UIViewController
!
open
var
fromViewController
:
UIViewController
!
open
var
transitionContext
:
UIViewControllerContextTransitioning
!
open
var
delay
:
TimeInterval
=
0
open
var
duration
:
TimeInterval
=
0.35
open
var
containerView
:
UIView
!
open
var
transitionView
=
UIView
()
fileprivate
var
modifiedDelay
:
TimeInterval
{
return
fromViewController
?
.
motionDelegate
?
.
motionModifyDelay
?(
motion
:
self
)
??
0
}
public
override
init
()
{
isPresenting
=
false
super
.
init
()
}
public
init
(
isPresenting
:
Bool
)
{
self
.
isPresenting
=
isPresenting
super
.
init
()
}
open
var
toView
:
UIView
{
return
toViewController
.
view
}
open
var
toSubviews
:
[
UIView
]
{
return
Motion
.
subviews
(
of
:
toView
)
}
open
var
fromView
:
UIView
{
return
fromViewController
.
view
}
open
var
fromSubviews
:
[
UIView
]
{
return
Motion
.
subviews
(
of
:
fromView
)
}
open
class
func
subviews
(
of
view
:
UIView
)
->
[
UIView
]
{
var
views
:
[
UIView
]
=
[]
Motion
.
subviews
(
of
:
view
,
views
:
&
views
)
return
views
}
open
class
func
subviews
(
of
view
:
UIView
,
views
:
inout
[
UIView
])
{
for
v
in
view
.
subviews
{
if
0
<
v
.
motionIdentifier
.
utf16
.
count
{
views
.
append
(
v
)
}
subviews
(
of
:
v
,
views
:
&
views
)
}
}
/**
Executes a block of code after a time delay.
Executes a block of code after a time delay.
- Parameter duration: An animation duration time.
- Parameter duration: An animation duration time.
- Parameter animations: An animation block.
- Parameter animations: An animation block.
...
@@ -95,93 +363,298 @@ public struct Motion {
...
@@ -95,93 +363,298 @@ public struct Motion {
the animations have completed.
the animations have completed.
*/
*/
@discardableResult
@discardableResult
public
static
func
delay
(
_
time
:
TimeInterval
,
execute
block
:
@escaping
()
->
Void
)
->
MotionDelayCancelBlock
?
{
open
class
func
delay
(
_
time
:
TimeInterval
,
execute
block
:
@escaping
()
->
Void
)
->
MotionDelayCancelBlock
?
{
func
asyncAfter
(
completion
:
@escaping
()
->
Void
)
{
func
asyncAfter
(
completion
:
@escaping
()
->
Void
)
{
DispatchQueue
.
main
.
asyncAfter
(
deadline
:
.
now
()
+
time
,
execute
:
completion
)
DispatchQueue
.
main
.
asyncAfter
(
deadline
:
DispatchTime
.
now
()
+
time
,
execute
:
completion
)
}
}
var
cancelable
:
MotionDelayCancelBlock
?
var
cancelable
:
MotionDelayCancelBlock
?
let
delayed
:
MotionDelayCancelBlock
=
{
let
delayed
:
MotionDelayCancelBlock
=
{
if
!
$0
{
if
!
$0
{
DispatchQueue
.
main
.
async
(
execute
:
block
)
DispatchQueue
.
main
.
async
(
execute
:
block
)
}
}
cancelable
=
nil
cancelable
=
nil
}
}
cancelable
=
delayed
cancelable
=
delayed
asyncAfter
{
asyncAfter
{
cancelable
?(
false
)
cancelable
?(
false
)
}
}
return
cancelable
return
cancelable
}
}
/**
/**
Cancels the delayed MotionDelayCancelBlock.
Cancels the delayed MotionDelayCancelBlock.
- Parameter delayed completion: An MotionDelayCancelBlock.
- Parameter delayed completion: An MotionDelayCancelBlock.
*/
*/
public
static
func
cancel
(
delayed
completion
:
MotionDelayCancelBlock
)
{
open
class
func
cancel
(
delayed
completion
:
MotionDelayCancelBlock
)
{
completion
(
true
)
completion
(
true
)
}
}
}
/**
extension
Motion
:
UIViewControllerAnimatedTransitioning
{
Disables the default animations set on CALayers.
@objc(animateTransition:)
- Parameter animations: A callback that wraps the animations to disable.
open
func
animateTransition
(
using
transitionContext
:
UIViewControllerContextTransitioning
)
{
*/
self
.
transitionContext
=
transitionContext
public
static
func
disable
(
animations
:
(()
->
Void
))
{
prepareToViewController
()
animate
(
duration
:
0
,
animations
:
animations
)
prepareFromViewController
()
}
fromViewController
.
motionDelegate
?
.
motion
?(
motion
:
self
,
willTransition
:
fromView
,
toView
:
toView
)
/**
Runs an animation with a specified duration.
Motion
.
delay
(
modifiedDelay
)
{
[
weak
self
]
in
- Parameter duration: An animation duration time.
guard
let
s
=
self
else
{
- Parameter animations: An animation block.
return
- Parameter timingFunction: An MotionAnimationTimingFunction value.
}
- Parameter completion: A completion block that is executed once
the animations have completed.
s
.
prepareContainerView
()
*/
s
.
prepareTransitionSnapshot
()
public
static
func
animate
(
duration
:
CFTimeInterval
,
timingFunction
:
MotionAnimationTimingFunction
=
.
easeInEaseOut
,
animations
:
(()
->
Void
),
completion
:
(()
->
Void
)?
=
nil
)
{
s
.
prepareTransitionPairs
()
CATransaction
.
begin
()
s
.
prepareTransitionView
()
CATransaction
.
setAnimationDuration
(
duration
)
s
.
prepareTransitionBackgroundView
()
CATransaction
.
setCompletionBlock
(
completion
)
s
.
prepareTransitionToView
()
CATransaction
.
setAnimationTimingFunction
(
MotionAnimationTimingFunctionToValue
(
timingFunction
:
timingFunction
))
s
.
prepareTransitionAnimation
()
animations
()
}
CATransaction
.
commit
()
}
}
@objc(transitionDuration:)
/**
open
func
transitionDuration
(
using
transitionContext
:
UIViewControllerContextTransitioning
?)
->
TimeInterval
{
return
delay
+
duration
}
}
extension
Motion
{
fileprivate
func
prepareToViewController
()
{
guard
let
v
=
transitionContext
.
viewController
(
forKey
:
.
to
)
else
{
return
}
toViewController
=
v
}
fileprivate
func
prepareFromViewController
()
{
guard
let
v
=
transitionContext
.
viewController
(
forKey
:
.
from
)
else
{
return
}
fromViewController
=
v
}
fileprivate
func
prepareContainerView
()
{
containerView
=
transitionContext
.
containerView
}
fileprivate
func
prepareTransitionSnapshot
()
{
transitionSnapshot
=
fromView
.
transitionSnapshot
(
afterUpdates
:
true
,
shouldHide
:
false
)
transitionSnapshot
.
frame
=
containerView
.
bounds
containerView
.
insertSubview
(
transitionSnapshot
,
aboveSubview
:
fromView
)
}
fileprivate
func
prepareTransitionPairs
()
{
for
from
in
fromSubviews
{
for
to
in
toSubviews
{
guard
to
.
motionIdentifier
==
from
.
motionIdentifier
else
{
continue
}
transitionPairs
.
append
((
from
,
to
))
}
}
}
fileprivate
func
prepareTransitionView
()
{
transitionView
.
frame
=
containerView
.
bounds
transitionView
.
isUserInteractionEnabled
=
false
containerView
.
insertSubview
(
transitionView
,
belowSubview
:
transitionSnapshot
)
}
fileprivate
func
prepareTransitionBackgroundView
()
{
transitionBackgroundView
.
backgroundColor
=
isPresenting
?
.
clear
:
fromView
.
backgroundColor
??
.
clear
transitionBackgroundView
.
frame
=
transitionView
.
bounds
transitionView
.
addSubview
(
transitionBackgroundView
)
}
fileprivate
func
prepareTransitionToView
()
{
toView
.
isHidden
=
isPresenting
containerView
.
insertSubview
(
toView
,
belowSubview
:
transitionView
)
toView
.
updateConstraints
()
toView
.
setNeedsLayout
()
toView
.
layoutIfNeeded
()
}
fileprivate
func
prepareTransitionAnimation
()
{
addTransitionAnimations
()
addBackgroundMotionAnimation
()
cleanupAnimation
()
removeTransitionSnapshot
()
}
}
extension
Motion
{
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
.
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
))
snapshotChildAnimations
.
append
(
cornerRadiusAnimation
)
snapshotChildAnimations
.
append
(
sizeAnimation
)
snapshotChildAnimations
.
append
(
Motion
.
position
(
x
:
to
.
bounds
.
width
/
2
,
y
:
to
.
bounds
.
height
/
2
))
let
d
=
transitionDuration
(
animations
:
to
.
motionAnimations
)
let
snapshot
=
from
.
transitionSnapshot
(
afterUpdates
:
true
)
transitionView
.
addSubview
(
snapshot
)
Motion
.
delay
(
motionDelay
(
animations
:
to
.
motionAnimations
))
{
[
weak
self
,
weak
to
]
in
guard
let
s
=
self
else
{
return
}
guard
let
v
=
to
else
{
return
}
let
tf
=
s
.
motionTimingFunction
(
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
)
}
}
fromViewController
.
motionDelegate
?
.
motionTransitionAnimation
?(
motion
:
self
)
toViewController
.
motionDelegate
?
.
motionTransitionAnimation
?(
motion
:
self
)
}
fileprivate
func
addBackgroundMotionAnimation
()
{
transitionBackgroundView
.
motion
(
.
backgroundColor
(
isPresenting
?
toView
.
backgroundColor
??
.
clear
:
.
clear
),
.
duration
(
transitionDuration
(
using
:
transitionContext
)))
}
}
extension
Motion
{
/**
Creates a CAAnimationGroup.
Creates a CAAnimationGroup.
- Parameter animations: An Array of CAAnimation objects.
- Parameter animations: An Array of CAAnimation objects.
- Parameter timingFunction: An MotionAnimationTimingFunction value.
- Parameter timingFunction: An MotionAnimationTimingFunction value.
- Parameter duration: An animation duration time for the group.
- Parameter duration: An animation duration time for the group.
- Returns: A CAAnimationGroup.
- Returns: A CAAnimationGroup.
*/
*/
public
static
func
animate
(
group
animations
:
[
CAAnimation
],
timingFunction
:
MotionAnimationTimingFunction
=
.
easeInEaseOut
,
duration
:
CFTimeInterval
=
0.5
)
->
CAAnimationGroup
{
internal
class
func
animate
(
group
animations
:
[
CAAnimation
],
timingFunction
:
MotionAnimationTimingFunction
=
.
easeInEaseOut
,
duration
:
CFTimeInterval
=
0.5
)
->
CAAnimationGroup
{
let
group
=
CAAnimationGroup
()
let
group
=
CAAnimationGroup
()
group
.
fillMode
=
MotionAnimationFillModeToValue
(
mode
:
.
forwards
)
group
.
fillMode
=
MotionAnimationFillModeToValue
(
mode
:
.
forwards
)
group
.
isRemovedOnCompletion
=
false
group
.
isRemovedOnCompletion
=
false
group
.
animations
=
animations
group
.
animations
=
animations
group
.
duration
=
duration
group
.
duration
=
duration
group
.
timingFunction
=
MotionAnimationTimingFunctionToValue
(
timingFunction
:
timingFunction
)
group
.
timingFunction
=
MotionAnimationTimingFunctionToValue
(
timingFunction
:
timingFunction
)
return
group
return
group
}
}
/**
Executes an animation block with a given delay and duration.
- Parameter delay time: A CFTimeInterval.
- Parameter duration: An animation duration time.
- Parameter animations: An animation block.
- Parameter completion: A completion block that is executed once
the animations have completed.
*/
public
static
func
animate
(
delay
time
:
CFTimeInterval
,
duration
:
CFTimeInterval
,
animations
:
@escaping
(()
->
Void
),
completion
:
(()
->
Void
)?
=
nil
)
{
delay
(
time
)
{
animate
(
duration
:
duration
,
animations
:
animations
,
completion
:
completion
)
}
}
}
}
extension
Motion
{
fileprivate
func
motionDelay
(
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
}
fileprivate
func
transitionDuration
(
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
}
fileprivate
func
motionTimingFunction
(
animations
:
[
MotionAnimation
])
->
MotionAnimationTimingFunction
{
var
t
=
MotionAnimationTimingFunction
.
easeInEaseOut
for
a
in
animations
{
switch
a
{
case
let
.
timingFunction
(
timingFunction
):
t
=
timingFunction
default
:
break
}
}
return
t
}
}
extension
Motion
{
fileprivate
func
cleanupAnimation
()
{
Motion
.
delay
(
transitionDuration
(
using
:
transitionContext
)
+
modifiedDelay
)
{
[
weak
self
]
in
guard
let
s
=
self
else
{
return
}
s
.
showToSubviews
()
s
.
clearTransitionView
()
s
.
clearTransitionPairs
()
s
.
completeTransition
()
}
}
fileprivate
func
removeTransitionSnapshot
()
{
Motion
.
delay
(
delay
)
{
[
weak
self
]
in
self
?
.
transitionSnapshot
.
removeFromSuperview
()
}
}
fileprivate
func
showToSubviews
()
{
toSubviews
.
forEach
{
$0
.
isHidden
=
false
}
toView
.
isHidden
=
false
}
fileprivate
func
clearTransitionPairs
()
{
transitionPairs
.
removeAll
()
}
fileprivate
func
clearTransitionView
()
{
transitionView
.
removeFromSuperview
()
transitionView
.
subviews
.
forEach
{
$0
.
removeFromSuperview
()
}
}
fileprivate
func
completeTransition
()
{
toViewController
.
motionDelegate
?
.
motion
?(
motion
:
self
,
didTransition
:
fromView
,
toView
:
toView
)
transitionContext
.
completeTransition
(
!
transitionContext
.
transitionWasCancelled
)
}
}
Sources/iOS/MotionAnimation.swift
View file @
cb8adf42
...
@@ -32,6 +32,7 @@ import UIKit
...
@@ -32,6 +32,7 @@ import UIKit
public
enum
MotionAnimationKeyPath
:
String
{
public
enum
MotionAnimationKeyPath
:
String
{
case
backgroundColor
case
backgroundColor
case
barTintColor
case
cornerRadius
case
cornerRadius
case
transform
case
transform
case
rotation
=
"transform.rotation"
case
rotation
=
"transform.rotation"
...
@@ -61,6 +62,7 @@ public enum MotionAnimation {
...
@@ -61,6 +62,7 @@ public enum MotionAnimation {
case
duration
(
TimeInterval
)
case
duration
(
TimeInterval
)
case
custom
(
CABasicAnimation
)
case
custom
(
CABasicAnimation
)
case
backgroundColor
(
UIColor
)
case
backgroundColor
(
UIColor
)
case
barTintColor
(
UIColor
)
case
cornerRadius
(
CGFloat
)
case
cornerRadius
(
CGFloat
)
case
transform
(
CATransform3D
)
case
transform
(
CATransform3D
)
case
rotationAngle
(
CGFloat
)
case
rotationAngle
(
CGFloat
)
...
@@ -92,7 +94,7 @@ public enum MotionAnimation {
...
@@ -92,7 +94,7 @@ public enum MotionAnimation {
}
}
extension
CALayer
{
extension
CALayer
{
/**
/**
A function that accepts CAAnimation objects and executes them on the
A function that accepts CAAnimation objects and executes them on the
view's backing layer.
view's backing layer.
...
@@ -123,7 +125,7 @@ extension CALayer {
...
@@ -123,7 +125,7 @@ extension CALayer {
}
}
}
}
}
}
/**
/**
A delegation function that is executed when the backing layer stops
A delegation function that is executed when the backing layer stops
running an animation.
running an animation.
...
@@ -243,6 +245,8 @@ extension CALayer {
...
@@ -243,6 +245,8 @@ extension CALayer {
a
.
append
(
animation
)
a
.
append
(
animation
)
case
let
.
backgroundColor
(
color
):
case
let
.
backgroundColor
(
color
):
a
.
append
(
Motion
.
background
(
color
:
color
))
a
.
append
(
Motion
.
background
(
color
:
color
))
case
let
.
barTintColor
(
color
):
a
.
append
(
Motion
.
barTint
(
color
:
color
))
case
let
.
cornerRadius
(
radius
):
case
let
.
cornerRadius
(
radius
):
a
.
append
(
Motion
.
corner
(
radius
:
radius
))
a
.
append
(
Motion
.
corner
(
radius
:
radius
))
case
let
.
transform
(
transform
):
case
let
.
transform
(
transform
):
...
@@ -300,7 +304,7 @@ extension CALayer {
...
@@ -300,7 +304,7 @@ extension CALayer {
default
:
break
default
:
break
}
}
}
}
let
g
=
Motion
.
animate
(
group
:
a
,
duration
:
d
)
let
g
=
Motion
.
animate
(
group
:
a
,
duration
:
d
)
g
.
fillMode
=
MotionAnimationFillModeToValue
(
mode
:
.
forwards
)
g
.
fillMode
=
MotionAnimationFillModeToValue
(
mode
:
.
forwards
)
g
.
isRemovedOnCompletion
=
false
g
.
isRemovedOnCompletion
=
false
...
@@ -325,6 +329,21 @@ extension UIView {
...
@@ -325,6 +329,21 @@ extension UIView {
}
}
}
}
/// The global position of a view.
open
var
motionPosition
:
CGPoint
{
return
superview
?
.
convert
(
position
,
to
:
nil
)
??
position
}
/// The layer.transform of a view.
open
var
motionTransform
:
CATransform3D
{
get
{
return
layer
.
transform
}
set
(
value
)
{
layer
.
transform
=
value
}
}
/// Computes the scale X axis value of the view.
/// Computes the scale X axis value of the view.
open
var
motionScaleX
:
CGFloat
{
open
var
motionScaleX
:
CGFloat
{
return
transform
.
a
return
transform
.
a
...
@@ -345,7 +364,7 @@ extension UIView {
...
@@ -345,7 +364,7 @@ extension UIView {
}
}
/**
/**
A function that accepts an Array of CAAnimation objects and executes
A function that accepts an Array of CAAnimation objects and executes
them on the view's backing layer.
them on the view's backing layer.
- Parameter animations: An Array of CAAnimations.
- Parameter animations: An Array of CAAnimations.
*/
*/
...
@@ -388,44 +407,55 @@ extension Motion {
...
@@ -388,44 +407,55 @@ extension Motion {
- Parameter color: A UIColor.
- Parameter color: A UIColor.
- Returns: A CABasicAnimation.
- Returns: A CABasicAnimation.
*/
*/
public
static
func
background
(
color
:
UIColor
)
->
CABasicAnimation
{
public
static
func
background
(
color
:
UIColor
)
->
CABasicAnimation
{
let
animation
=
CABasicAnimation
(
keyPath
:
.
backgroundColor
)
let
animation
=
CABasicAnimation
(
keyPath
:
.
backgroundColor
)
animation
.
toValue
=
color
.
cgColor
animation
.
toValue
=
color
.
cgColor
return
animation
return
animation
}
}
/**
Creates a CABasicAnimation for the barTintColor key path.
- Parameter color: A UIColor.
- Returns: A CABasicAnimation.
*/
public
static
func
barTint
(
color
:
UIColor
)
->
CABasicAnimation
{
let
animation
=
CABasicAnimation
(
keyPath
:
.
barTintColor
)
animation
.
toValue
=
color
.
cgColor
return
animation
}
/**
/**
Creates a CABasicAnimation for the cornerRadius key path.
Creates a CABasicAnimation for the cornerRadius key path.
- Parameter radius: A CGFloat.
- Parameter radius: A CGFloat.
- Returns: A CABasicAnimation.
- Returns: A CABasicAnimation.
*/
*/
public
static
func
corner
(
radius
:
CGFloat
)
->
CABasicAnimation
{
public
static
func
corner
(
radius
:
CGFloat
)
->
CABasicAnimation
{
let
animation
=
CABasicAnimation
(
keyPath
:
.
cornerRadius
)
let
animation
=
CABasicAnimation
(
keyPath
:
.
cornerRadius
)
animation
.
toValue
=
radius
animation
.
toValue
=
radius
return
animation
return
animation
}
}
/**
/**
Creates a CABasicAnimation for the transform key path.
Creates a CABasicAnimation for the transform key path.
- Parameter transform: A CATransform3D object.
- Parameter transform: A CATransform3D object.
- Returns: A CABasicAnimation.
- Returns: A CABasicAnimation.
*/
*/
public
static
func
transform
(
transform
:
CATransform3D
)
->
CABasicAnimation
{
public
static
func
transform
(
transform
:
CATransform3D
)
->
CABasicAnimation
{
let
animation
=
CABasicAnimation
(
keyPath
:
.
transform
)
let
animation
=
CABasicAnimation
(
keyPath
:
.
transform
)
animation
.
toValue
=
NSValue
(
caTransform3D
:
transform
)
animation
.
toValue
=
NSValue
(
caTransform3D
:
transform
)
return
animation
return
animation
}
}
/**
/**
Creates a CABasicAnimation for the transform.rotation key path.
Creates a CABasicAnimation for the transform.rotation key path.
- Parameter angle: An optional CGFloat.
- Parameter angle: An optional CGFloat.
- Returns: A CABasicAnimation.
- Returns: A CABasicAnimation.
*/
*/
public
static
func
rotation
(
angle
:
CGFloat
)
->
CABasicAnimation
{
public
static
func
rotation
(
angle
:
CGFloat
)
->
CABasicAnimation
{
let
animation
=
CABasicAnimation
(
keyPath
:
.
rotation
)
let
animation
=
CABasicAnimation
(
keyPath
:
.
rotation
)
animation
.
toValue
=
NSNumber
(
value
:
Double
(
CGFloat
(
M_PI
)
*
angle
/
180
))
animation
.
toValue
=
NSNumber
(
value
:
Double
(
CGFloat
(
M_PI
)
*
angle
/
180
))
return
animation
return
animation
}
}
/**
/**
Creates a CABasicAnimation for the transform.rotation.x key path.
Creates a CABasicAnimation for the transform.rotation.x key path.
...
@@ -433,32 +463,32 @@ extension Motion {
...
@@ -433,32 +463,32 @@ extension Motion {
- Returns: A CABasicAnimation.
- Returns: A CABasicAnimation.
*/
*/
public
static
func
rotationX
(
angle
:
CGFloat
)
->
CABasicAnimation
{
public
static
func
rotationX
(
angle
:
CGFloat
)
->
CABasicAnimation
{
let
animation
=
CABasicAnimation
(
keyPath
:
.
rotationX
)
let
animation
=
CABasicAnimation
(
keyPath
:
.
rotationX
)
animation
.
toValue
=
NSNumber
(
value
:
Double
(
CGFloat
(
M_PI
)
*
angle
/
180
))
animation
.
toValue
=
NSNumber
(
value
:
Double
(
CGFloat
(
M_PI
)
*
angle
/
180
))
return
animation
return
animation
}
}
/**
/**
Creates a CABasicAnimation for the transform.rotation.y key path.
Creates a CABasicAnimation for the transform.rotation.y key path.
- Parameter angle: An optional CGFloat.
- Parameter angle: An optional CGFloat.
- Returns: A CABasicAnimation.
- Returns: A CABasicAnimation.
*/
*/
public
static
func
rotationY
(
angle
:
CGFloat
)
->
CABasicAnimation
{
public
static
func
rotationY
(
angle
:
CGFloat
)
->
CABasicAnimation
{
let
animation
=
CABasicAnimation
(
keyPath
:
.
rotationY
)
let
animation
=
CABasicAnimation
(
keyPath
:
.
rotationY
)
animation
.
toValue
=
NSNumber
(
value
:
Double
(
CGFloat
(
M_PI
)
*
angle
/
180
))
animation
.
toValue
=
NSNumber
(
value
:
Double
(
CGFloat
(
M_PI
)
*
angle
/
180
))
return
animation
return
animation
}
}
/**
/**
Creates a CABasicAnimation for the transform.rotation.z key path.
Creates a CABasicAnimation for the transform.rotation.z key path.
- Parameter angle: An optional CGFloat.
- Parameter angle: An optional CGFloat.
- Returns: A CABasicAnimation.
- Returns: A CABasicAnimation.
*/
*/
public
static
func
rotationZ
(
angle
:
CGFloat
)
->
CABasicAnimation
{
public
static
func
rotationZ
(
angle
:
CGFloat
)
->
CABasicAnimation
{
let
animation
=
CABasicAnimation
(
keyPath
:
.
rotationZ
)
let
animation
=
CABasicAnimation
(
keyPath
:
.
rotationZ
)
animation
.
toValue
=
NSNumber
(
value
:
Double
(
CGFloat
(
M_PI
)
*
angle
/
180
))
animation
.
toValue
=
NSNumber
(
value
:
Double
(
CGFloat
(
M_PI
)
*
angle
/
180
))
return
animation
return
animation
}
}
/**
/**
Creates a CABasicAnimation for the transform.rotation key path.
Creates a CABasicAnimation for the transform.rotation key path.
...
@@ -503,95 +533,95 @@ extension Motion {
...
@@ -503,95 +533,95 @@ extension Motion {
animation
.
toValue
=
NSNumber
(
value
:
Double
(
CGFloat
(
M_PI
)
*
2
*
rotations
))
animation
.
toValue
=
NSNumber
(
value
:
Double
(
CGFloat
(
M_PI
)
*
2
*
rotations
))
return
animation
return
animation
}
}
/**
/**
Creates a CABasicAnimation for the transform.scale key path.
Creates a CABasicAnimation for the transform.scale key path.
- Parameter to scale: A CGFloat.
- Parameter to scale: A CGFloat.
- Returns: A CABasicAnimation.
- Returns: A CABasicAnimation.
*/
*/
public
static
func
scale
(
to
scale
:
CGFloat
)
->
CABasicAnimation
{
public
static
func
scale
(
to
scale
:
CGFloat
)
->
CABasicAnimation
{
let
animation
=
CABasicAnimation
(
keyPath
:
.
scale
)
let
animation
=
CABasicAnimation
(
keyPath
:
.
scale
)
animation
.
toValue
=
NSNumber
(
value
:
Double
(
scale
))
animation
.
toValue
=
NSNumber
(
value
:
Double
(
scale
))
return
animation
return
animation
}
}
/**
/**
Creates a CABasicAnimation for the transform.scale.x key path.
Creates a CABasicAnimation for the transform.scale.x key path.
- Parameter to scale: A CGFloat.
- Parameter to scale: A CGFloat.
- Returns: A CABasicAnimation.
- Returns: A CABasicAnimation.
*/
*/
public
static
func
scaleX
(
to
scale
:
CGFloat
)
->
CABasicAnimation
{
public
static
func
scaleX
(
to
scale
:
CGFloat
)
->
CABasicAnimation
{
let
animation
=
CABasicAnimation
(
keyPath
:
.
scaleX
)
let
animation
=
CABasicAnimation
(
keyPath
:
.
scaleX
)
animation
.
toValue
=
NSNumber
(
value
:
Double
(
scale
))
animation
.
toValue
=
NSNumber
(
value
:
Double
(
scale
))
return
animation
return
animation
}
}
/**
/**
Creates a CABasicAnimation for the transform.scale.y key path.
Creates a CABasicAnimation for the transform.scale.y key path.
- Parameter to scale: A CGFloat.
- Parameter to scale: A CGFloat.
- Returns: A CABasicAnimation.
- Returns: A CABasicAnimation.
*/
*/
public
static
func
scaleY
(
to
scale
:
CGFloat
)
->
CABasicAnimation
{
public
static
func
scaleY
(
to
scale
:
CGFloat
)
->
CABasicAnimation
{
let
animation
=
CABasicAnimation
(
keyPath
:
.
scaleY
)
let
animation
=
CABasicAnimation
(
keyPath
:
.
scaleY
)
animation
.
toValue
=
NSNumber
(
value
:
Double
(
scale
))
animation
.
toValue
=
NSNumber
(
value
:
Double
(
scale
))
return
animation
return
animation
}
}
/**
/**
Creates a CABasicAnimation for the transform.scale.z key path.
Creates a CABasicAnimation for the transform.scale.z key path.
- Parameter to scale: A CGFloat.
- Parameter to scale: A CGFloat.
- Returns: A CABasicAnimation.
- Returns: A CABasicAnimation.
*/
*/
public
static
func
scaleZ
(
to
scale
:
CGFloat
)
->
CABasicAnimation
{
public
static
func
scaleZ
(
to
scale
:
CGFloat
)
->
CABasicAnimation
{
let
animation
=
CABasicAnimation
(
keyPath
:
.
scaleZ
)
let
animation
=
CABasicAnimation
(
keyPath
:
.
scaleZ
)
animation
.
toValue
=
NSNumber
(
value
:
Double
(
scale
))
animation
.
toValue
=
NSNumber
(
value
:
Double
(
scale
))
return
animation
return
animation
}
}
/**
/**
Creates a CABasicAnimation for the transform.translation key path.
Creates a CABasicAnimation for the transform.translation key path.
- Parameter point: A CGPoint.
- Parameter point: A CGPoint.
- Returns: A CABasicAnimation.
- Returns: A CABasicAnimation.
*/
*/
public
static
func
translate
(
to
point
:
CGPoint
)
->
CABasicAnimation
{
public
static
func
translate
(
to
point
:
CGPoint
)
->
CABasicAnimation
{
let
animation
=
CABasicAnimation
(
keyPath
:
.
translation
)
let
animation
=
CABasicAnimation
(
keyPath
:
.
translation
)
animation
.
toValue
=
NSValue
(
cgPoint
:
point
)
animation
.
toValue
=
NSValue
(
cgPoint
:
point
)
return
animation
return
animation
}
}
/**
/**
Creates a CABasicAnimation for the transform.translation.x key path.
Creates a CABasicAnimation for the transform.translation.x key path.
- Parameter to translation: A CGFloat.
- Parameter to translation: A CGFloat.
- Returns: A CABasicAnimation.
- Returns: A CABasicAnimation.
*/
*/
public
static
func
translateX
(
to
translation
:
CGFloat
)
->
CABasicAnimation
{
public
static
func
translateX
(
to
translation
:
CGFloat
)
->
CABasicAnimation
{
let
animation
=
CABasicAnimation
(
keyPath
:
.
translationX
)
let
animation
=
CABasicAnimation
(
keyPath
:
.
translationX
)
animation
.
toValue
=
NSNumber
(
value
:
Double
(
translation
))
animation
.
toValue
=
NSNumber
(
value
:
Double
(
translation
))
return
animation
return
animation
}
}
/**
/**
Creates a CABasicAnimation for the transform.translation.y key path.
Creates a CABasicAnimation for the transform.translation.y key path.
- Parameter to translation: A CGFloat.
- Parameter to translation: A CGFloat.
- Returns: A CABasicAnimation.
- Returns: A CABasicAnimation.
*/
*/
public
static
func
translateY
(
to
translation
:
CGFloat
)
->
CABasicAnimation
{
public
static
func
translateY
(
to
translation
:
CGFloat
)
->
CABasicAnimation
{
let
animation
=
CABasicAnimation
(
keyPath
:
.
translationY
)
let
animation
=
CABasicAnimation
(
keyPath
:
.
translationY
)
animation
.
toValue
=
NSNumber
(
value
:
Double
(
translation
))
animation
.
toValue
=
NSNumber
(
value
:
Double
(
translation
))
return
animation
return
animation
}
}
/**
/**
Creates a CABasicAnimation for the transform.translation.z key path.
Creates a CABasicAnimation for the transform.translation.z key path.
- Parameter to translation: A CGFloat.
- Parameter to translation: A CGFloat.
- Returns: A CABasicAnimation.
- Returns: A CABasicAnimation.
*/
*/
public
static
func
translateZ
(
to
translation
:
CGFloat
)
->
CABasicAnimation
{
public
static
func
translateZ
(
to
translation
:
CGFloat
)
->
CABasicAnimation
{
let
animation
=
CABasicAnimation
(
keyPath
:
.
translationZ
)
let
animation
=
CABasicAnimation
(
keyPath
:
.
translationZ
)
animation
.
toValue
=
NSNumber
(
value
:
Double
(
translation
))
animation
.
toValue
=
NSNumber
(
value
:
Double
(
translation
))
return
animation
return
animation
}
}
/**
/**
Creates a CABasicAnimation for the position key path.
Creates a CABasicAnimation for the position key path.
- Parameter x: A CGFloat.
- Parameter x: A CGFloat.
...
@@ -599,10 +629,10 @@ extension Motion {
...
@@ -599,10 +629,10 @@ extension Motion {
- Returns: A CABasicAnimation.
- Returns: A CABasicAnimation.
*/
*/
public
static
func
position
(
x
:
CGFloat
,
y
:
CGFloat
)
->
CABasicAnimation
{
public
static
func
position
(
x
:
CGFloat
,
y
:
CGFloat
)
->
CABasicAnimation
{
let
animation
=
CABasicAnimation
(
keyPath
:
.
position
)
let
animation
=
CABasicAnimation
(
keyPath
:
.
position
)
animation
.
toValue
=
NSValue
(
cgPoint
:
CGPoint
(
x
:
x
,
y
:
y
))
animation
.
toValue
=
NSValue
(
cgPoint
:
CGPoint
(
x
:
x
,
y
:
y
))
return
animation
return
animation
}
}
/**
/**
Creates a CABasicAnimation for the position key path.
Creates a CABasicAnimation for the position key path.
...
@@ -614,17 +644,17 @@ extension Motion {
...
@@ -614,17 +644,17 @@ extension Motion {
animation
.
toValue
=
NSValue
(
cgPoint
:
point
)
animation
.
toValue
=
NSValue
(
cgPoint
:
point
)
return
animation
return
animation
}
}
/**
/**
Creates a CABasicAnimation for the shadowPath key path.
Creates a CABasicAnimation for the shadowPath key path.
- Parameter path: A CGPath.
- Parameter path: A CGPath.
- Returns: A CABasicAnimation.
- Returns: A CABasicAnimation.
*/
*/
public
static
func
shadow
(
path
:
CGPath
)
->
CABasicAnimation
{
public
static
func
shadow
(
path
:
CGPath
)
->
CABasicAnimation
{
let
animation
=
CABasicAnimation
(
keyPath
:
.
shadowPath
)
let
animation
=
CABasicAnimation
(
keyPath
:
.
shadowPath
)
animation
.
toValue
=
path
animation
.
toValue
=
path
return
animation
return
animation
}
}
/**
/**
Creates a CABasicAnimation for the opacity key path.
Creates a CABasicAnimation for the opacity key path.
...
...
Sources/iOS/MotionTransition.swift
deleted
100644 → 0
View file @
b77365ad
/*
* Copyright (C) 2015 - 2017, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.com>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of CosmicMind nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import
UIKit
fileprivate
var
MotionTransitionInstanceKey
:
UInt8
=
0
fileprivate
var
MotionTransitionInstanceControllerKey
:
UInt8
=
0
fileprivate
struct
MotionTransitionInstance
{
fileprivate
var
identifier
:
String
fileprivate
var
animations
:
[
MotionAnimation
]
}
fileprivate
struct
MotionTransitionInstanceController
{
fileprivate
var
isEnabled
:
Bool
}
extension
UIViewController
:
UIViewControllerTransitioningDelegate
{
/// MotionTransitionInstanceController Reference.
fileprivate
var
motionTransition
:
MotionTransitionInstanceController
{
get
{
return
AssociatedObject
(
base
:
self
,
key
:
&
MotionTransitionInstanceControllerKey
)
{
return
MotionTransitionInstanceController
(
isEnabled
:
false
)
}
}
set
(
value
)
{
AssociateObject
(
base
:
self
,
key
:
&
MotionTransitionInstanceControllerKey
,
value
:
value
)
}
}
open
var
isMotionTransitionEnabled
:
Bool
{
get
{
return
motionTransition
.
isEnabled
}
set
(
value
)
{
if
value
{
modalPresentationStyle
=
.
custom
transitioningDelegate
=
self
}
motionTransition
.
isEnabled
=
value
}
}
}
extension
UIViewController
{
open
func
animationController
(
forPresented
presented
:
UIViewController
,
presenting
:
UIViewController
,
source
:
UIViewController
)
->
UIViewControllerAnimatedTransitioning
?
{
return
isMotionTransitionEnabled
?
MotionTransition
(
isPresenting
:
true
)
:
nil
}
open
func
animationController
(
forDismissed
dismissed
:
UIViewController
)
->
UIViewControllerAnimatedTransitioning
?
{
return
isMotionTransitionEnabled
?
MotionTransition
()
:
nil
}
open
func
presentationController
(
forPresented
presented
:
UIViewController
,
presenting
:
UIViewController
?,
source
:
UIViewController
)
->
UIPresentationController
?
{
return
isMotionTransitionEnabled
?
MotionTransitionPresentationController
(
presentedViewController
:
presented
,
presenting
:
presenting
)
:
nil
}
}
extension
UIViewController
{
open
func
navigationController
(
_
navigationController
:
UINavigationController
,
animationControllerFor
operation
:
UINavigationControllerOperation
,
from
fromVC
:
UIViewController
,
to
toVC
:
UIViewController
)
->
UIViewControllerAnimatedTransitioning
?
{
return
isMotionTransitionEnabled
?
MotionTransition
(
isPresenting
:
operation
==
.
push
)
:
nil
}
}
extension
UIViewController
{
open
func
tabBarController
(
_
tabBarController
:
UITabBarController
,
animationControllerForTransitionFrom
fromVC
:
UIViewController
,
to
toVC
:
UIViewController
)
->
UIViewControllerAnimatedTransitioning
?
{
return
isMotionTransitionEnabled
?
MotionTransition
()
:
nil
}
}
extension
UIView
{
/// The global position of a view.
open
var
motionPosition
:
CGPoint
{
return
superview
?
.
convert
(
position
,
to
:
nil
)
??
position
}
/// MaterialTransitionItem Reference.
fileprivate
var
motionTransition
:
MotionTransitionInstance
{
get
{
return
AssociatedObject
(
base
:
self
,
key
:
&
MotionTransitionInstanceKey
)
{
return
MotionTransitionInstance
(
identifier
:
""
,
animations
:
[])
}
}
set
(
value
)
{
AssociateObject
(
base
:
self
,
key
:
&
MotionTransitionInstanceKey
,
value
:
value
)
}
}
open
var
motionTransitionIdentifier
:
String
{
get
{
return
motionTransition
.
identifier
}
set
(
value
)
{
motionTransition
.
identifier
=
value
}
}
open
var
motionTransitionAnimations
:
[
MotionAnimation
]
{
get
{
return
motionTransition
.
animations
}
set
(
value
)
{
motionTransition
.
animations
=
value
}
}
open
func
motionTransitionSnapshot
(
afterUpdates
:
Bool
)
->
UIView
{
isHidden
=
false
(
self
as?
Pulseable
)?
.
pulse
.
pulseLayer
?
.
isHidden
=
true
let
oldCornerRadius
=
cornerRadius
cornerRadius
=
0
let
oldBackgroundColor
=
backgroundColor
backgroundColor
=
.
clear
let
oldTransform
=
transform
transform
=
.
identity
let
v
=
snapshotView
(
afterScreenUpdates
:
afterUpdates
)
!
cornerRadius
=
oldCornerRadius
backgroundColor
=
oldBackgroundColor
transform
=
oldTransform
let
contentView
=
v
.
subviews
.
first
!
contentView
.
cornerRadius
=
cornerRadius
contentView
.
masksToBounds
=
true
v
.
motionTransitionIdentifier
=
motionTransitionIdentifier
v
.
position
=
motionPosition
v
.
bounds
=
bounds
v
.
cornerRadius
=
cornerRadius
v
.
zPosition
=
zPosition
v
.
opacity
=
opacity
v
.
isOpaque
=
isOpaque
v
.
anchorPoint
=
anchorPoint
v
.
masksToBounds
=
masksToBounds
v
.
borderColor
=
borderColor
v
.
borderWidth
=
borderWidth
v
.
shadowRadius
=
shadowRadius
v
.
shadowOpacity
=
shadowOpacity
v
.
shadowColor
=
shadowColor
v
.
shadowOffset
=
shadowOffset
v
.
contentMode
=
contentMode
v
.
transform
=
transform
v
.
backgroundColor
=
backgroundColor
isHidden
=
true
(
self
as?
Pulseable
)?
.
pulse
.
pulseLayer
?
.
isHidden
=
false
return
v
}
}
open
class
MotionTransitionPresentationController
:
UIPresentationController
{
open
override
func
presentationTransitionWillBegin
()
{
guard
nil
!=
containerView
else
{
return
}
presentedViewController
.
transitionCoordinator
?
.
animate
(
alongsideTransition
:
{
(
context
)
in
print
(
"Animating"
)
})
print
(
"presentationTransitionWillBegin"
)
}
open
override
func
presentationTransitionDidEnd
(
_
completed
:
Bool
)
{
print
(
"presentationTransitionDidEnd"
)
}
open
override
func
dismissalTransitionWillBegin
()
{
guard
nil
!=
containerView
else
{
return
}
presentedViewController
.
transitionCoordinator
?
.
animate
(
alongsideTransition
:
{
(
context
)
in
print
(
"Animating"
)
})
print
(
"dismissalTransitionWillBegin"
)
}
open
override
func
dismissalTransitionDidEnd
(
_
completed
:
Bool
)
{
print
(
"dismissalTransitionDidEnd"
)
}
open
override
var
frameOfPresentedViewInContainerView
:
CGRect
{
return
containerView
?
.
bounds
??
.
zero
}
}
open
class
MotionTransition
:
NSObject
{
open
var
isPresenting
:
Bool
open
fileprivate
(
set
)
var
transitionPairs
=
[(
UIView
,
UIView
)]()
open
var
transitionSnapshot
:
UIView
!
open
let
transitionBackgroundView
=
UIView
()
open
var
toViewController
:
UIViewController
!
open
var
fromViewController
:
UIViewController
!
open
var
transitionContext
:
UIViewControllerContextTransitioning
!
open
var
delay
:
TimeInterval
=
0
open
var
duration
:
TimeInterval
=
0.35
open
var
containerView
:
UIView
!
open
var
transitionView
=
UIView
()
public
override
init
()
{
isPresenting
=
false
super
.
init
()
}
public
init
(
isPresenting
:
Bool
)
{
self
.
isPresenting
=
isPresenting
super
.
init
()
}
open
var
toView
:
UIView
{
return
toViewController
.
view
}
open
var
toSubviews
:
[
UIView
]
{
return
subviews
(
of
:
toView
)
}
open
var
fromView
:
UIView
{
return
fromViewController
.
view
}
open
var
fromSubviews
:
[
UIView
]
{
return
subviews
(
of
:
fromView
)
}
open
func
subviews
(
of
view
:
UIView
)
->
[
UIView
]
{
var
views
:
[
UIView
]
=
[]
subviews
(
of
:
view
,
views
:
&
views
)
return
views
}
open
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
MotionTransition
:
UIViewControllerAnimatedTransitioning
{
@objc(animateTransition:)
open
func
animateTransition
(
using
transitionContext
:
UIViewControllerContextTransitioning
)
{
self
.
transitionContext
=
transitionContext
prepareToViewController
()
prepareFromViewController
()
prepareContainerView
()
prepareTransitionSnapshot
()
prepareTransitionPairs
()
prepareTransitionView
()
prepareTransitionBackgroundView
()
prepareTransitionToView
()
prepareTransitionAnimation
()
}
@objc(transitionDuration:)
open
func
transitionDuration
(
using
transitionContext
:
UIViewControllerContextTransitioning
?)
->
TimeInterval
{
return
delay
+
duration
}
}
extension
MotionTransition
{
fileprivate
func
prepareToViewController
()
{
guard
let
v
=
transitionContext
.
viewController
(
forKey
:
.
to
)
else
{
return
}
toViewController
=
v
}
fileprivate
func
prepareFromViewController
()
{
guard
let
v
=
transitionContext
.
viewController
(
forKey
:
.
from
)
else
{
return
}
fromViewController
=
v
}
fileprivate
func
prepareContainerView
()
{
containerView
=
transitionContext
.
containerView
}
fileprivate
func
prepareTransitionSnapshot
()
{
transitionSnapshot
=
fromView
.
motionTransitionSnapshot
(
afterUpdates
:
true
)
transitionSnapshot
.
frame
=
containerView
.
bounds
containerView
.
addSubview
(
transitionSnapshot
)
}
fileprivate
func
prepareTransitionPairs
()
{
for
from
in
fromSubviews
{
guard
0
<
from
.
motionTransitionIdentifier
.
utf16
.
count
else
{
continue
}
for
to
in
toSubviews
{
guard
to
.
motionTransitionIdentifier
==
from
.
motionTransitionIdentifier
else
{
continue
}
transitionPairs
.
append
((
from
,
to
))
}
}
}
fileprivate
func
prepareTransitionView
()
{
transitionView
.
frame
=
containerView
.
bounds
containerView
.
insertSubview
(
transitionView
,
belowSubview
:
transitionSnapshot
)
}
fileprivate
func
prepareTransitionBackgroundView
()
{
transitionBackgroundView
.
backgroundColor
=
fromView
.
backgroundColor
transitionBackgroundView
.
frame
=
transitionView
.
bounds
transitionView
.
addSubview
(
transitionBackgroundView
)
}
fileprivate
func
prepareTransitionToView
()
{
if
isPresenting
{
containerView
.
insertSubview
(
toView
,
belowSubview
:
transitionView
)
}
toView
.
isHidden
=
false
toView
.
updateConstraints
()
toView
.
setNeedsLayout
()
toView
.
layoutIfNeeded
()
}
fileprivate
func
prepareTransitionAnimation
()
{
addTransitionAnimations
()
addBackgroundMotionAnimation
()
cleanupAnimation
()
hideFromView
()
removeTransitionSnapshot
()
}
}
extension
MotionTransition
{
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
.
cornerRadius
)
snapshotAnimations
.
append
(
sizeAnimation
)
snapshotAnimations
.
append
(
cornerRadiusAnimation
)
snapshotAnimations
.
append
(
Motion
.
position
(
to
:
to
.
motionPosition
))
snapshotAnimations
.
append
(
Motion
.
rotation
(
angle
:
to
.
motionRotationAngle
))
snapshotAnimations
.
append
(
Motion
.
background
(
color
:
to
.
backgroundColor
??
.
clear
))
snapshotChildAnimations
.
append
(
cornerRadiusAnimation
)
snapshotChildAnimations
.
append
(
sizeAnimation
)
snapshotChildAnimations
.
append
(
Motion
.
position
(
x
:
to
.
bounds
.
width
/
2
,
y
:
to
.
bounds
.
height
/
2
))
let
d
=
motionDuration
(
animations
:
to
.
motionTransitionAnimations
)
let
snapshot
=
from
.
motionTransitionSnapshot
(
afterUpdates
:
true
)
transitionView
.
addSubview
(
snapshot
)
Motion
.
delay
(
motionDelay
(
animations
:
to
.
motionTransitionAnimations
))
{
[
weak
self
,
weak
to
]
in
guard
let
s
=
self
else
{
return
}
guard
let
v
=
to
else
{
return
}
let
tf
=
s
.
motionTimingFunction
(
animations
:
v
.
motionTransitionAnimations
)
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
)
}
}
}
fileprivate
func
addBackgroundMotionAnimation
()
{
transitionBackgroundView
.
motion
(
.
backgroundColor
(
toView
.
backgroundColor
??
.
clear
),
.
duration
(
transitionDuration
(
using
:
transitionContext
)))
}
}
extension
MotionTransition
{
fileprivate
func
motionDelay
(
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
}
fileprivate
func
motionDuration
(
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
}
fileprivate
func
motionTimingFunction
(
animations
:
[
MotionAnimation
])
->
MotionAnimationTimingFunction
{
var
t
=
MotionAnimationTimingFunction
.
easeInEaseOut
for
a
in
animations
{
switch
a
{
case
let
.
timingFunction
(
timingFunction
):
t
=
timingFunction
default
:
break
}
}
return
t
}
}
extension
MotionTransition
{
fileprivate
func
cleanupAnimation
()
{
Motion
.
delay
(
transitionDuration
(
using
:
transitionContext
))
{
[
weak
self
]
in
guard
let
s
=
self
else
{
return
}
s
.
hideToSubviews
()
s
.
clearTransitionView
()
s
.
clearTransitionPairs
()
s
.
completeTransition
()
}
}
fileprivate
func
hideFromView
()
{
Motion
.
delay
(
delay
)
{
[
weak
self
]
in
self
?
.
fromView
.
isHidden
=
true
}
}
fileprivate
func
removeTransitionSnapshot
()
{
Motion
.
delay
(
delay
)
{
[
weak
self
]
in
self
?
.
transitionSnapshot
.
removeFromSuperview
()
}
}
fileprivate
func
hideToSubviews
()
{
toSubviews
.
forEach
{
$0
.
isHidden
=
false
}
}
fileprivate
func
clearTransitionPairs
()
{
transitionPairs
.
removeAll
()
}
fileprivate
func
clearTransitionView
()
{
transitionView
.
removeFromSuperview
()
transitionView
.
subviews
.
forEach
{
$0
.
removeFromSuperview
()
}
}
fileprivate
func
completeTransition
()
{
transitionContext
.
completeTransition
(
!
transitionContext
.
transitionWasCancelled
)
}
}
Sources/iOS/NavigationBar.swift
View file @
cb8adf42
...
@@ -98,9 +98,12 @@ open class NavigationBar: UINavigationBar {
...
@@ -98,9 +98,12 @@ open class NavigationBar: UINavigationBar {
/// A property that accesses the backing layer's background
/// A property that accesses the backing layer's background
@IBInspectable
@IBInspectable
open
override
var
backgroundColor
:
UIColor
?
{
open
override
var
backgroundColor
:
UIColor
?
{
didSet
{
get
{
barTintColor
=
backgroundColor
return
barTintColor
}
}
set
(
value
)
{
barTintColor
=
value
}
}
}
/**
/**
...
...
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