├── AnimationExampleAdvanced
├── Assets.xcassets
│ ├── Contents.json
│ ├── close.imageset
│ │ ├── Close.png
│ │ ├── Close@2x.png
│ │ ├── Close@3x.png
│ │ └── Contents.json
│ ├── AppIcon.appiconset
│ │ ├── 1024.png
│ │ ├── 114.png
│ │ ├── 120.png
│ │ ├── 180.png
│ │ ├── 29.png
│ │ ├── 40.png
│ │ ├── 57.png
│ │ ├── 58.png
│ │ ├── 60.png
│ │ ├── 80.png
│ │ ├── 87.png
│ │ └── Contents.json
│ ├── bruce1.imageset
│ │ ├── bruce1.png
│ │ └── Contents.json
│ ├── madonna.imageset
│ │ ├── madonna.png
│ │ └── Contents.json
│ ├── kateperry.imageset
│ │ ├── kateperry.png
│ │ └── Contents.json
│ ├── mjackson.imageset
│ │ ├── mjackson.png
│ │ └── Contents.json
│ ├── profile1.imageset
│ │ ├── profile1.png
│ │ └── Contents.json
│ ├── profile2.imageset
│ │ ├── profile2.png
│ │ └── Contents.json
│ ├── profile3.imageset
│ │ ├── profile3.png
│ │ └── Contents.json
│ ├── profile4.imageset
│ │ ├── profile4.png
│ │ └── Contents.json
│ ├── PlusButton.imageset
│ │ ├── PlusButton.png
│ │ └── Contents.json
│ ├── playButton.imageset
│ │ ├── playButton.png
│ │ └── Contents.json
│ ├── 3dotsButton.imageset
│ │ ├── 3dotsButton.png
│ │ └── Contents.json
│ ├── downloadButton.imageset
│ │ ├── downloadButton.png
│ │ └── Contents.json
│ ├── handLikeButton.imageset
│ │ ├── handLikeButton.png
│ │ └── Contents.json
│ └── forbiddenButton.imageset
│ │ ├── forbiddenButton.png
│ │ └── Contents.json
├── README.md
├── Info.plist
├── ViewController.swift
├── Base.lproj
│ ├── Main.storyboard
│ └── LaunchScreen.storyboard
├── Common
│ ├── Navigation
│ │ └── TransitionCordinator.swift
│ └── ViewControllerTransitions
│ │ ├── PopAnimator.swift
│ │ └── PushAnimator.swift
├── Views
│ └── Cells
│ │ ├── MainTableViewCell.swift
│ │ └── MainTableViewCell.xib
├── Controllers
│ ├── PushedViewController.swift
│ ├── MainViewController+DataSource.swift
│ ├── MainViewController.xib
│ ├── MainViewController+ProtocolTransition.swift
│ ├── MainViewController.swift
│ └── PushedViewController.xib
├── AppDelegate.swift
└── Helpers
│ └── Helpers.swift
└── AnimationExampleAdvanced.xcodeproj
├── project.xcworkspace
├── xcuserdata
│ ├── fran.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
│ └── fobarrio.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
├── contents.xcworkspacedata
└── xcshareddata
│ └── IDEWorkspaceChecks.plist
├── xcuserdata
├── fobarrio.xcuserdatad
│ └── xcschemes
│ │ └── xcschememanagement.plist
└── fran.xcuserdatad
│ └── xcschemes
│ └── xcschememanagement.plist
├── xcshareddata
└── xcschemes
│ └── AnimationExampleAdvanced.xcscheme
└── project.pbxproj
/AnimationExampleAdvanced/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/close.imageset/Close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/close.imageset/Close.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/AppIcon.appiconset/1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/AppIcon.appiconset/1024.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/AppIcon.appiconset/114.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/AppIcon.appiconset/114.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/AppIcon.appiconset/120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/AppIcon.appiconset/120.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/AppIcon.appiconset/180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/AppIcon.appiconset/180.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/AppIcon.appiconset/29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/AppIcon.appiconset/29.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/AppIcon.appiconset/40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/AppIcon.appiconset/40.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/AppIcon.appiconset/57.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/AppIcon.appiconset/57.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/AppIcon.appiconset/58.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/AppIcon.appiconset/58.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/AppIcon.appiconset/60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/AppIcon.appiconset/60.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/AppIcon.appiconset/80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/AppIcon.appiconset/80.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/AppIcon.appiconset/87.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/AppIcon.appiconset/87.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/bruce1.imageset/bruce1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/bruce1.imageset/bruce1.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/close.imageset/Close@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/close.imageset/Close@2x.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/close.imageset/Close@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/close.imageset/Close@3x.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/madonna.imageset/madonna.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/madonna.imageset/madonna.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/kateperry.imageset/kateperry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/kateperry.imageset/kateperry.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/mjackson.imageset/mjackson.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/mjackson.imageset/mjackson.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/profile1.imageset/profile1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/profile1.imageset/profile1.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/profile2.imageset/profile2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/profile2.imageset/profile2.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/profile3.imageset/profile3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/profile3.imageset/profile3.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/profile4.imageset/profile4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/profile4.imageset/profile4.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/PlusButton.imageset/PlusButton.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/PlusButton.imageset/PlusButton.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/playButton.imageset/playButton.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/playButton.imageset/playButton.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/3dotsButton.imageset/3dotsButton.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/3dotsButton.imageset/3dotsButton.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/downloadButton.imageset/downloadButton.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/downloadButton.imageset/downloadButton.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/handLikeButton.imageset/handLikeButton.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/handLikeButton.imageset/handLikeButton.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/forbiddenButton.imageset/forbiddenButton.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced/Assets.xcassets/forbiddenButton.imageset/forbiddenButton.png
--------------------------------------------------------------------------------
/AnimationExampleAdvanced.xcodeproj/project.xcworkspace/xcuserdata/fran.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced.xcodeproj/project.xcworkspace/xcuserdata/fran.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/AnimationExampleAdvanced.xcodeproj/project.xcworkspace/xcuserdata/fobarrio.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/franobarrio/animation-transition-viewcontroller-advanced/HEAD/AnimationExampleAdvanced.xcodeproj/project.xcworkspace/xcuserdata/fobarrio.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/AnimationExampleAdvanced.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/AnimationExampleAdvanced.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/bruce1.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "bruce1.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/madonna.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "madonna.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/mjackson.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "mjackson.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/profile1.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "profile1.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/profile2.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "profile2.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/profile3.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "profile3.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/profile4.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "profile4.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/PlusButton.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "PlusButton.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/kateperry.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "kateperry.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/playButton.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "playButton.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/3dotsButton.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "3dotsButton.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/downloadButton.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "downloadButton.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/forbiddenButton.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "forbiddenButton.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/handLikeButton.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "handLikeButton.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/AnimationExampleAdvanced.xcodeproj/xcuserdata/fobarrio.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | AnimationExample.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/close.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Close.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "Close@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "Close@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/AnimationExampleAdvanced.xcodeproj/xcuserdata/fran.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | AnimationExample.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 | AnimationExampleAdvanced.xcscheme_^#shared#^_
13 |
14 | orderHint
15 | 0
16 |
17 |
18 | SuppressBuildableAutocreation
19 |
20 | A19C219B21471E8600CDC6ED
21 |
22 | primary
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/README.md:
--------------------------------------------------------------------------------
1 | # README
2 |
3 |
4 | * Copyright (c) Francisco Obarrio - fobarrio@gmail.com - https://twitter.com/fran_obarrio
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | *
23 | *
24 | * Basically ... Feel Free to use this code as you want !
25 | * BTW I'm available for freelance work :D
26 |
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"}]}
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | VC Animation II
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/ViewController.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Francisco Obarrio - fobarrio@gmail.com
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | * THE SOFTWARE.
21 | */
22 |
23 | import UIKit
24 |
25 | class ViewController: UIViewController {
26 |
27 | override func viewDidLoad() {
28 | super.viewDidLoad()
29 | // Do any additional setup after loading the view, typically from a nib.
30 | }
31 |
32 | override func didReceiveMemoryWarning() {
33 | super.didReceiveMemoryWarning()
34 | // Dispose of any resources that can be recreated.
35 | }
36 |
37 |
38 | }
39 |
40 |
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Common/Navigation/TransitionCordinator.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Francisco Obarrio - fobarrio@gmail.com
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | * THE SOFTWARE.
21 | */
22 |
23 | import UIKit
24 |
25 |
26 | // NavigationController Delegate for Transition Coordinator
27 | class TransitionCoordinator: NSObject, UINavigationControllerDelegate {
28 | func navigationController(_ navigationController: UINavigationController,
29 | animationControllerFor operation: UINavigationControllerOperation,
30 | from fromVC: UIViewController,
31 | to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
32 |
33 |
34 | switch operation {
35 | case .push:
36 | //return PushAnimator()
37 | return PushAnimator(duration: TimeInterval(UINavigationControllerHideShowBarDuration))
38 | case .pop:
39 | //return PopAnimator()
40 | return PopAnimator(duration: TimeInterval(UINavigationControllerHideShowBarDuration))
41 | default:
42 | return nil
43 | }
44 |
45 |
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Views/Cells/MainTableViewCell.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Francisco Obarrio - fobarrio@gmail.com
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | * THE SOFTWARE.
21 | */
22 |
23 | import UIKit
24 |
25 | class MainTableViewCell: UITableViewCell {
26 |
27 |
28 | @IBOutlet weak var cellBackground: UIView!
29 | @IBOutlet weak var profileImageView: UIImageView!
30 | @IBOutlet weak var plusImageView: UIImageView!
31 | @IBOutlet weak var playImageView: UIImageView!
32 | @IBOutlet weak var likeImageView: UIImageView!
33 | @IBOutlet weak var cancelImageView: UIImageView!
34 | @IBOutlet weak var backgroundImageView: UIImageView!
35 |
36 | @IBOutlet weak var mainTitleLbl: UILabel!
37 | @IBOutlet weak var albumTitle: UILabel!
38 | @IBOutlet weak var albumYearLbl: UILabel!
39 |
40 |
41 |
42 | // MARK: Initialization
43 | fileprivate var stateCel:Int = 0
44 |
45 | required init?(coder aDecoder: NSCoder) {
46 | super.init(coder: aDecoder)
47 |
48 | }
49 |
50 | override func awakeFromNib() {
51 | super.awakeFromNib()
52 |
53 | setupView()
54 |
55 | }
56 |
57 | override func prepareForReuse() {
58 | super.prepareForReuse()
59 | }
60 |
61 |
62 | func setupCell(backgroundImage: String, profileImage: String, backgroundColor: String, title: String, album: String, year: String) {
63 | self.profileImageView.image = UIImage(named: profileImage)
64 | self.backgroundImageView.image = UIImage(named: backgroundImage)
65 | self.cellBackground.backgroundColor = backgroundColor.hexColor
66 | self.mainTitleLbl.text = title
67 | self.albumTitle.text = album
68 | self.albumYearLbl.text = year
69 | }
70 |
71 | func setupView() {
72 |
73 | self.cellBackground.layer.borderWidth = 0.0
74 | self.cellBackground.layer.borderColor = UIColor.clear.cgColor
75 | self.cellBackground.layer.cornerRadius = 10
76 | self.cellBackground.layer.masksToBounds = false
77 |
78 | self.selectionStyle = .none
79 |
80 | }
81 |
82 |
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Controllers/PushedViewController.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 |
3 |
4 | class PushedViewController: UIViewController {
5 |
6 | // ImageViews
7 | @IBOutlet weak var profileIV: UIImageView!
8 | @IBOutlet weak var plusIV: UIImageView!
9 | @IBOutlet weak var playIV: UIImageView!
10 | @IBOutlet weak var likeIV: UIImageView!
11 | @IBOutlet weak var cancelIV: UIImageView!
12 | @IBOutlet weak var backgroundIV: UIImageView!
13 |
14 | // Views
15 | @IBOutlet weak var topBackground: UIView!
16 | @IBOutlet weak var bottomBackground: UIView!
17 |
18 | // Labels
19 | @IBOutlet weak var titleLbl: UILabel!
20 | @IBOutlet weak var albumLabel: UILabel!
21 | @IBOutlet weak var yearLabel: UILabel!
22 |
23 |
24 | // Vars
25 | var selectedProfileImage: String?
26 | var selectedBackgroundImage: String?
27 | var mainTitle: String?
28 | var album: String?
29 | var year: String?
30 | var topHexColor: String?
31 |
32 |
33 | override func viewDidLoad() {
34 | super.viewDidLoad()
35 |
36 | if let topColor = topHexColor {
37 | topBackground.backgroundColor = topColor.hexColor
38 | }
39 |
40 | // Setup Profile Image
41 | if let imageProfile = selectedProfileImage {
42 | profileIV.image = UIImage(named: imageProfile)
43 | }
44 |
45 | // Setup Profile Image
46 | if let imageBackground = selectedBackgroundImage {
47 | backgroundIV.image = UIImage(named: imageBackground)
48 | }
49 | // Setup Title
50 | if let selectedTitle = mainTitle {
51 | self.titleLbl.text = selectedTitle
52 | }
53 | // Setup Album
54 | if let selectedAlbum = album {
55 | self.albumLabel.text = selectedAlbum
56 | }
57 | // Setup Year
58 | if let selectedYear = year {
59 | self.yearLabel.text = selectedYear
60 | }
61 |
62 |
63 | let tap = UITapGestureRecognizer(target: self, action: #selector(doubleTapped))
64 | self.view.addGestureRecognizer(tap)
65 |
66 | }
67 |
68 | @objc func doubleTapped() {
69 | self.navigationController?.popViewController(animated: true)
70 | }
71 |
72 |
73 | }
74 |
75 | extension PushedViewController : animTransitionable
76 | {
77 | var profileImageView: UIImageView {
78 | return profileIV
79 | }
80 |
81 | var backgroundImageView: UIImageView {
82 | return backgroundIV
83 | }
84 |
85 | var plusImageView: UIImageView {
86 | return plusIV
87 | }
88 |
89 | var playImageView: UIImageView {
90 | return playIV
91 | }
92 |
93 | var likeImageView: UIImageView {
94 | return likeIV
95 | }
96 |
97 | var cancelImageView: UIImageView {
98 | return cancelIV
99 | }
100 |
101 | var backgroundColor: UIView {
102 | return topBackground
103 | }
104 |
105 | var cellBackground: UIView {
106 | return bottomBackground
107 | }
108 |
109 | var bigTitle: UILabel {
110 | return titleLbl
111 | }
112 |
113 | var albumLbl: UILabel {
114 | return albumLabel
115 | }
116 |
117 | var yearLbl: UILabel {
118 | return yearLabel
119 | }
120 |
121 | }
122 |
123 |
--------------------------------------------------------------------------------
/AnimationExampleAdvanced.xcodeproj/xcshareddata/xcschemes/AnimationExampleAdvanced.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Francisco Obarrio - fobarrio@gmail.com
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | * THE SOFTWARE.
21 | */
22 |
23 | import UIKit
24 |
25 | @UIApplicationMain
26 | class AppDelegate: UIResponder, UIApplicationDelegate {
27 |
28 | var window: UIWindow?
29 |
30 | //let transitionCoordinator = TransitionCoordinator()
31 |
32 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
33 |
34 |
35 | let whiteVC = MainViewController()
36 |
37 | window = UIWindow(frame: UIScreen.main.bounds)
38 | let nav = UINavigationController(rootViewController: whiteVC)
39 | nav.isNavigationBarHidden = true
40 |
41 | //Add TransitionCoordinator as navigation controller's delegate
42 | //nav.delegate = transitionCoordinator
43 |
44 | window?.rootViewController = nav
45 | window?.makeKeyAndVisible()
46 |
47 | // Override point for customization after application launch.
48 | return true
49 | }
50 |
51 | func applicationWillResignActive(_ application: UIApplication) {
52 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
53 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
54 | }
55 |
56 | func applicationDidEnterBackground(_ application: UIApplication) {
57 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
58 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
59 | }
60 |
61 | func applicationWillEnterForeground(_ application: UIApplication) {
62 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
63 | }
64 |
65 | func applicationDidBecomeActive(_ application: UIApplication) {
66 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
67 | }
68 |
69 | func applicationWillTerminate(_ application: UIApplication) {
70 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
71 | }
72 |
73 |
74 | }
75 |
76 |
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Controllers/MainViewController+DataSource.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Francisco Obarrio - fobarrio@gmail.com
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | * THE SOFTWARE.
21 | */
22 |
23 | import UIKit
24 |
25 | // MARK: - DataSource
26 | extension MainViewController: UITableViewDataSource {
27 |
28 |
29 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
30 |
31 | let cell = tableView.dequeueReusableCell(withIdentifier: "mainCell") as! MainTableViewCell
32 | cell.setupCell(backgroundImage: dictionaryDataArray[indexPath.section]["backgroundImage"]!,
33 | profileImage: dictionaryDataArray[indexPath.section]["profileImage"]!, backgroundColor: dictionaryDataArray[indexPath.section]["hexBackgroundColor"]!, title: dictionaryDataArray[indexPath.section]["title"]!, album: dictionaryDataArray[indexPath.section]["album"]!, year: dictionaryDataArray[indexPath.section]["year"]!)
34 |
35 | return cell
36 |
37 | }
38 |
39 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
40 |
41 | self.selectedIndexPath = indexPath
42 |
43 | doAnimFadeOut()
44 |
45 | let finalVC = PushedViewController()
46 | finalVC.selectedProfileImage = dictionaryDataArray[indexPath.section]["profileImage"]!
47 | finalVC.selectedBackgroundImage = dictionaryDataArray[indexPath.section]["backgroundImage"]!
48 | finalVC.mainTitle = dictionaryDataArray[indexPath.section]["title"]!
49 | finalVC.album = dictionaryDataArray[indexPath.section]["album"]!
50 | finalVC.year = dictionaryDataArray[indexPath.section]["year"]!
51 | finalVC.topHexColor = dictionaryDataArray[indexPath.section]["hexBackgroundColor"]!
52 |
53 |
54 | navigationController?.delegate = transition
55 |
56 | DispatchQueue.main.asyncAfter(deadline: .now() + (Double(self.tableView.visibleCells.count) * 0.15 )) { // change 2 to desired number of seconds
57 | self.navigationController?.pushViewController(finalVC, animated: true)
58 | }
59 |
60 |
61 | }
62 |
63 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
64 | return UITableViewAutomaticDimension
65 | }
66 |
67 | func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
68 | return UITableViewAutomaticDimension
69 | }
70 |
71 | func numberOfSections(in tableView: UITableView) -> Int {
72 | return dictionaryDataArray.count
73 | }
74 |
75 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
76 | return 1
77 | }
78 |
79 | func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
80 | return 20
81 | }
82 |
83 | //Let's insert a headerView to create the spacing we want
84 | func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
85 | let view = UIView()
86 | view.frame = CGRect(x: 0, y: 0, width: tableView.frame.width, height: 20) //size of a standard tableViewCell
87 | view.backgroundColor = UIColor.clear
88 | return view
89 | }
90 |
91 | }
92 |
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Controllers/MainViewController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Controllers/MainViewController+ProtocolTransition.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Francisco Obarrio - fobarrio@gmail.com
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | * THE SOFTWARE.
21 | */
22 |
23 | import UIKit
24 |
25 | // MARK: - Protocol for Transition
26 | extension MainViewController : animTransitionable
27 | {
28 |
29 | // Profile Image
30 | var profileImageView: UIImageView {
31 | if let indexPath = selectedIndexPath {
32 | let cell = tableView?.cellForRow(at: indexPath) as! MainTableViewCell
33 | return cell.profileImageView
34 | }
35 | return UIImageView()
36 | }
37 |
38 | // Background Image
39 | var backgroundImageView: UIImageView {
40 | if let indexPath = selectedIndexPath {
41 | let cell = tableView?.cellForRow(at: indexPath) as! MainTableViewCell
42 | return cell.backgroundImageView
43 | }
44 | return UIImageView()
45 | }
46 |
47 |
48 | // Plus Button
49 | var plusImageView: UIImageView {
50 | if let indexPath = selectedIndexPath {
51 | let cell = tableView?.cellForRow(at: indexPath) as! MainTableViewCell
52 | return cell.plusImageView
53 | }
54 | return UIImageView()
55 | }
56 |
57 | // Play Button
58 | var playImageView: UIImageView {
59 | if let indexPath = selectedIndexPath {
60 | let cell = tableView?.cellForRow(at: indexPath) as! MainTableViewCell
61 | return cell.playImageView
62 | }
63 | return UIImageView()
64 | }
65 |
66 | // Like Button
67 | var likeImageView: UIImageView {
68 | if let indexPath = selectedIndexPath {
69 | let cell = tableView?.cellForRow(at: indexPath) as! MainTableViewCell
70 | return cell.likeImageView
71 | }
72 | return UIImageView()
73 | }
74 |
75 | // Cancel Button
76 | var cancelImageView: UIImageView {
77 | if let indexPath = selectedIndexPath {
78 | let cell = tableView?.cellForRow(at: indexPath) as! MainTableViewCell
79 | return cell.cancelImageView
80 | }
81 | return UIImageView()
82 | }
83 |
84 |
85 |
86 | // Background Color
87 | var backgroundColor: UIView {
88 | return backgroundView
89 | }
90 |
91 | // Cell Background
92 | var cellBackground: UIView {
93 | if let indexPath = selectedIndexPath {
94 | let cell = tableView?.cellForRow(at: indexPath) as! MainTableViewCell
95 | return cell.cellBackground
96 | }
97 | return UIView()
98 | }
99 |
100 | // Labels
101 | var bigTitle: UILabel {
102 | if let indexPath = selectedIndexPath {
103 | let cell = tableView?.cellForRow(at: indexPath) as! MainTableViewCell
104 | return cell.mainTitleLbl
105 | }
106 | return UILabel()
107 | }
108 | var albumLbl: UILabel {
109 | if let indexPath = selectedIndexPath {
110 | let cell = tableView?.cellForRow(at: indexPath) as! MainTableViewCell
111 | return cell.albumTitle
112 | }
113 | return UILabel()
114 | }
115 | var yearLbl: UILabel {
116 | if let indexPath = selectedIndexPath {
117 | let cell = tableView?.cellForRow(at: indexPath) as! MainTableViewCell
118 | return cell.albumYearLbl
119 | }
120 | return UILabel()
121 | }
122 |
123 |
124 |
125 |
126 |
127 | }
128 |
129 |
130 |
131 |
132 |
133 |
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Controllers/MainViewController.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Francisco Obarrio - fobarrio@gmail.com
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | * THE SOFTWARE.
21 | */
22 |
23 | import UIKit
24 |
25 |
26 | class MainViewController: UIViewController, UINavigationControllerDelegate, UITableViewDelegate {
27 |
28 |
29 | @IBOutlet weak var tableView: UITableView!
30 | @IBOutlet var backgroundView: UIView!
31 |
32 |
33 | let transition = TransitionCoordinator()
34 |
35 | var selectedIndexPath: IndexPath!
36 |
37 | // This is an array of dictionaries.
38 | var dictionaryDataArray: [[String: String]] = [
39 | [
40 | "profileImage": "profile1",
41 | "backgroundImage": "kateperry",
42 | "album": "One of the Boys",
43 | "year": "2003",
44 | "hexBackgroundColor": "d15d63",
45 | "title": "Kate Perry"
46 | ],
47 | [
48 | "profileImage": "profile2",
49 | "backgroundImage": "bruce1",
50 | "album": "Born in the USA",
51 | "year": "1984",
52 | "hexBackgroundColor": "2d72b5",
53 | "title": "Bruce Springsteen"
54 | ],
55 | [
56 | "profileImage": "profile3",
57 | "backgroundImage": "mjackson",
58 | "album": "Thriller",
59 | "year": "1982",
60 | "hexBackgroundColor": "fdeba9",
61 | "title": "Michael Jackson"
62 | ],
63 |
64 | [
65 | "profileImage": "profile4",
66 | "backgroundImage": "madonna",
67 | "album": "Like a Prayer",
68 | "year": "1998",
69 | "hexBackgroundColor": "S1B733",
70 | "title": "Madonna"
71 | ]
72 |
73 |
74 | ]
75 |
76 | override func viewDidLoad() {
77 | super.viewDidLoad()
78 |
79 | self.tableView.register(UINib(nibName: "MainTableViewCell", bundle: nil), forCellReuseIdentifier: "mainCell")
80 |
81 | }
82 |
83 | override func didReceiveMemoryWarning() {
84 | super.didReceiveMemoryWarning()
85 | // Dispose of any resources that can be recreated.
86 | }
87 |
88 | override func viewDidAppear(_ animated: Bool) {
89 | super.viewDidAppear(animated)
90 |
91 | if let transitionCoordinator = navigationController?.transitionCoordinator,
92 | let fromVC = transitionCoordinator.viewController(forKey: UITransitionContextViewControllerKey.from),
93 | let toVC = transitionCoordinator.viewController(forKey: UITransitionContextViewControllerKey.to),
94 | fromVC is PushedViewController,
95 | toVC is MainViewController {
96 |
97 | doAnimFadeIn()
98 |
99 | }
100 | }
101 |
102 | func doAnimFadeIn() {
103 |
104 | let cells = self.tableView.indexPathsForVisibleRows
105 | var index = 0
106 |
107 | if let cells = cells, cells.count > 0 {
108 | for x in 0.. 0 {
128 | for x in 0..> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
55 | case 6: // RGB (24-bit)
56 | (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
57 | case 8: // ARGB (32-bit)
58 | (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
59 | default:
60 | return .clear
61 | }
62 | return UIColor(red: CGFloat(r) / 255, green: CGFloat(g) / 255, blue: CGFloat(b) / 255, alpha: CGFloat(a) / 255)
63 | }
64 | }
65 |
66 | func attributedString(from string: String, lineSpacing: CGFloat = 1.0, font: UIFont, fontColor: UIColor = UIColor.black, alignment: NSTextAlignment = .natural, kerning: CGFloat = 1.0) -> NSMutableAttributedString {
67 |
68 | let style = NSMutableParagraphStyle()
69 | style.lineSpacing = lineSpacing
70 | style.alignment = alignment
71 |
72 | let attrs = [
73 | NSAttributedStringKey.font: font,
74 | NSAttributedStringKey.foregroundColor: fontColor,
75 | NSAttributedStringKey.paragraphStyle: style,
76 | NSAttributedStringKey.kern: kerning
77 | ] as [NSAttributedStringKey : Any]
78 |
79 | let attrStr = NSMutableAttributedString(string: string, attributes: attrs)
80 |
81 | return attrStr
82 | }
83 |
84 | func addParabolaWithMax(maxPoint: CGPoint, inRect boundingRect: CGRect) -> UIBezierPath {
85 |
86 | func halfPoint1D(p0: CGFloat, p2: CGFloat, control: CGFloat) -> CGFloat {
87 | return 2 * control - p0 / 2 - p2 / 2
88 | }
89 |
90 | let path = UIBezierPath()
91 |
92 | let p0 = CGPoint(x: 0, y: boundingRect.maxY)
93 | let p2 = CGPoint(x: boundingRect.maxX, y: boundingRect.maxY)
94 |
95 | let p1 = CGPoint(x: halfPoint1D(p0: p0.x, p2: p2.x, control: maxPoint.x),
96 | y: halfPoint1D(p0: p0.y, p2: p2.y, control: maxPoint.y))
97 |
98 | path.move(to: p0)
99 | path.addQuadCurve(to: p2, controlPoint: p1)
100 | return path
101 | }
102 |
103 | func duplicateLabel(label: UILabel) -> UILabel {
104 | let newLabel = UILabel(frame: label.frame)
105 | newLabel.font = label.font
106 | newLabel.textAlignment = label.textAlignment
107 | newLabel.textColor = label.textColor
108 | newLabel.backgroundColor = label.backgroundColor
109 |
110 | //newLabel.adjustsFontSizeToFitWidth = true
111 |
112 | return newLabel
113 | }
114 |
115 | extension UIFont {
116 |
117 | /**
118 | Will return the best font conforming to the descriptor which will fit in the provided bounds.
119 | */
120 | static func bestFittingFontSize(for text: String, in bounds: CGRect, fontDescriptor: UIFontDescriptor, additionalAttributes: [NSAttributedStringKey: Any]? = nil) -> CGFloat {
121 | let constrainingDimension = min(bounds.width, bounds.height)
122 | let properBounds = CGRect(origin: .zero, size: bounds.size)
123 | var attributes = additionalAttributes ?? [:]
124 |
125 | let infiniteBounds = CGSize(width: CGFloat.infinity, height: CGFloat.infinity)
126 | var bestFontSize: CGFloat = constrainingDimension
127 |
128 | for fontSize in stride(from: bestFontSize, through: 0, by: -1) {
129 | let newFont = UIFont(descriptor: fontDescriptor, size: fontSize)
130 | attributes[.font] = newFont
131 |
132 | let currentFrame = text.boundingRect(with: infiniteBounds, options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: attributes, context: nil)
133 |
134 | if properBounds.contains(currentFrame) {
135 | bestFontSize = fontSize
136 | break
137 | }
138 | }
139 | return bestFontSize
140 | }
141 |
142 | static func bestFittingFont(for text: String, in bounds: CGRect, fontDescriptor: UIFontDescriptor, additionalAttributes: [NSAttributedStringKey: Any]? = nil) -> UIFont {
143 | let bestSize = bestFittingFontSize(for: text, in: bounds, fontDescriptor: fontDescriptor, additionalAttributes: additionalAttributes)
144 | return UIFont(descriptor: fontDescriptor, size: bestSize)
145 | }
146 | }
147 |
148 | extension UILabel {
149 |
150 | /// Will auto resize the contained text to a font size which fits the frames bounds.
151 | /// Uses the pre-set font to dynamically determine the proper sizing
152 | func fitTextToBounds() {
153 | guard let text = text, let currentFont = font else { return }
154 |
155 | let bestFittingFont = UIFont.bestFittingFont(for: text, in: bounds, fontDescriptor: currentFont.fontDescriptor, additionalAttributes: basicStringAttributes)
156 | font = bestFittingFont
157 | }
158 |
159 | private var basicStringAttributes: [NSAttributedStringKey: Any] {
160 | var attribs = [NSAttributedStringKey: Any]()
161 |
162 | let paragraphStyle = NSMutableParagraphStyle()
163 | paragraphStyle.alignment = self.textAlignment
164 | paragraphStyle.lineBreakMode = self.lineBreakMode
165 | attribs[.paragraphStyle] = paragraphStyle
166 |
167 | return attribs
168 | }
169 | }
170 |
171 |
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Views/Cells/MainTableViewCell.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
38 |
45 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Common/ViewControllerTransitions/PopAnimator.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import QuartzCore
3 |
4 |
5 | class PopAnimator: NSObject, UIViewControllerAnimatedTransitioning {
6 |
7 | var duration : TimeInterval
8 |
9 | init(duration : TimeInterval) {
10 | self.duration = duration
11 | }
12 |
13 | func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
14 | return duration
15 | }
16 |
17 | func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
18 |
19 | let containerView = transitionContext.containerView
20 |
21 |
22 | guard let fromVC = transitionContext.viewController(forKey: .from) as? animTransitionable,
23 | let toVC = transitionContext.viewController(forKey: .to) as? animTransitionable else {
24 | transitionContext.completeTransition(false)
25 | return
26 | }
27 |
28 |
29 |
30 |
31 | let fromViewController = transitionContext.viewController(forKey: .from)!
32 | let toViewController = transitionContext.viewController(forKey: .to)!
33 |
34 | // Plus Image
35 | let imageViewSnapshotPlus = UIImageView(image: fromVC.plusImageView.image)
36 | imageViewSnapshotPlus.contentMode = .scaleAspectFit
37 |
38 | //Profile Image
39 | let imageViewSnapshotProfile = UIImageView(image: fromVC.profileImageView.image)
40 | imageViewSnapshotProfile.contentMode = .scaleAspectFit
41 |
42 | //Background Image
43 | let imageViewSnapshotBackground = UIImageView(image: fromVC.backgroundImageView.image)
44 | imageViewSnapshotBackground.contentMode = .scaleAspectFit
45 |
46 |
47 | //Like Image
48 | let imageViewSnapshotLike = UIImageView(image: fromVC.likeImageView.image)
49 | imageViewSnapshotLike.contentMode = .scaleAspectFit
50 |
51 | //Play Image
52 | let imageViewSnapshotPlay = UIImageView(image: fromVC.playImageView.image)
53 | imageViewSnapshotPlay.contentMode = .scaleAspectFit
54 |
55 | //Cancel Image
56 | let imageViewSnapshotCancel = UIImageView(image: fromVC.cancelImageView.image)
57 | imageViewSnapshotCancel.contentMode = .scaleAspectFit
58 |
59 |
60 |
61 | //Background View With Correct Color
62 | let backgroundView = UIView()
63 | backgroundView.frame = fromVC.backgroundColor.frame
64 | backgroundView.backgroundColor = UIColor.white
65 | containerView.addSubview(backgroundView)
66 |
67 |
68 | // Title
69 | let titleLabel = duplicateLabel(label: fromVC.bigTitle)
70 | titleLabel.text = fromVC.bigTitle.text
71 | titleLabel.backgroundColor = UIColor.clear
72 | titleLabel.frame = containerView.convert(fromVC.bigTitle.frame, from: fromVC.bigTitle.superview)
73 | titleLabel.sizeToFit()
74 |
75 | // Album
76 | let albumLabel = duplicateLabel(label: fromVC.albumLbl)
77 | albumLabel.text = fromVC.albumLbl.text
78 | albumLabel.backgroundColor = UIColor.clear
79 | albumLabel.frame = containerView.convert(fromVC.albumLbl.frame, from: fromVC.albumLbl.superview)
80 | albumLabel.sizeToFit()
81 |
82 |
83 | // Year
84 | let yearLabel = duplicateLabel(label: fromVC.yearLbl)
85 | yearLabel.text = fromVC.yearLbl.text
86 | yearLabel.backgroundColor = UIColor.clear
87 | yearLabel.frame = containerView.convert(fromVC.yearLbl.frame, from: fromVC.yearLbl.superview)
88 | yearLabel.sizeToFit()
89 |
90 |
91 |
92 |
93 | // Cell Background
94 | let cellBackground = UIView()
95 | cellBackground.backgroundColor = fromVC.backgroundColor.backgroundColor
96 | cellBackground.layer.cornerRadius = fromVC.backgroundColor.layer.cornerRadius
97 | cellBackground.layer.masksToBounds = fromVC.backgroundColor.layer.masksToBounds
98 | cellBackground.frame = containerView.convert(fromVC.backgroundColor.frame, from: fromVC.backgroundColor.superview)
99 | cellBackground.setNeedsLayout()
100 |
101 |
102 | containerView.addSubview(fromViewController.view)
103 | containerView.addSubview(toViewController.view)
104 |
105 | containerView.addSubview(cellBackground)
106 |
107 |
108 |
109 |
110 |
111 | // Top
112 | containerView.addSubview(imageViewSnapshotProfile)
113 | containerView.addSubview(imageViewSnapshotBackground)
114 | containerView.addSubview(imageViewSnapshotPlus)
115 |
116 | // Down
117 | containerView.addSubview(imageViewSnapshotCancel)
118 | containerView.addSubview(imageViewSnapshotPlay)
119 | containerView.addSubview(imageViewSnapshotLike)
120 |
121 |
122 | // Title Label
123 | containerView.addSubview(titleLabel)
124 | containerView.addSubview(albumLabel)
125 | containerView.addSubview(yearLabel)
126 |
127 |
128 |
129 |
130 |
131 | containerView.bringSubview(toFront: imageViewSnapshotPlus)
132 |
133 |
134 | fromViewController.view.isHidden = true
135 | toViewController.view.isHidden = true
136 |
137 | // TOP
138 | imageViewSnapshotPlus.frame = containerView.convert(fromVC.plusImageView.frame, from: fromVC.plusImageView.superview)
139 | imageViewSnapshotProfile.frame = containerView.convert(fromVC.profileImageView.frame, from: fromVC.profileImageView.superview)
140 | imageViewSnapshotBackground.frame = containerView.convert(fromVC.backgroundImageView.frame, from: fromVC.backgroundImageView.superview)
141 |
142 |
143 | // BOTTOM
144 | imageViewSnapshotCancel.frame = containerView.convert(fromVC.cancelImageView.frame, from: fromVC.cancelImageView.superview)
145 | imageViewSnapshotPlay.frame = containerView.convert(fromVC.playImageView.frame, from: fromVC.playImageView.superview)
146 | imageViewSnapshotLike.frame = containerView.convert(fromVC.likeImageView.frame, from: fromVC.likeImageView.superview)
147 |
148 |
149 |
150 |
151 | let frameBackground: CGRect = containerView.convert(toVC.cellBackground.frame, from: toVC.cellBackground.superview)
152 |
153 | // TOP
154 | let frameProfile: CGRect = containerView.convert(toVC.profileImageView.frame, from: toVC.profileImageView.superview)
155 | let frameBackgroundImage: CGRect = containerView.convert(toVC.backgroundImageView.frame, from: toVC.backgroundImageView.superview)
156 | let framePlus: CGRect = containerView.convert(toVC.plusImageView.frame, from: toVC.plusImageView.superview)
157 |
158 | // BOTTOM
159 | let framePlay: CGRect = containerView.convert(toVC.playImageView.frame, from: toVC.playImageView.superview)
160 |
161 |
162 |
163 | // Animators
164 | let animator1 = {
165 | UIViewPropertyAnimator(duration: 0.4, dampingRatio: 0.8) {
166 |
167 | // HAY QUE PONER BIEN LOS TAMAÑOS DE LAS IMAGENES
168 |
169 | let backgroundX = cellBackground.frame.minX + (cellBackground.frame.width * 5 / 100)
170 | let backgroundWidth = cellBackground.frame.width - (cellBackground.frame.width * 10 / 100)
171 |
172 | // BACKGROUND
173 | cellBackground.frame = frameBackground
174 | cellBackground.layer.cornerRadius = toVC.cellBackground.layer.cornerRadius
175 |
176 |
177 | // Label
178 | titleLabel.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
179 | titleLabel.frame = containerView.convert(toVC.bigTitle.frame, from: toVC.bigTitle.superview)
180 |
181 | //albumLabel.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
182 | albumLabel.frame = containerView.convert(toVC.albumLbl.frame, from: toVC.albumLbl.superview)
183 | albumLabel.textAlignment = .left
184 |
185 | //yearLabel.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
186 | yearLabel.frame = containerView.convert(toVC.yearLbl.frame, from: toVC.yearLbl.superview)
187 | yearLabel.textAlignment = .left
188 |
189 |
190 | imageViewSnapshotCancel.frame = containerView.convert(toVC.cancelImageView.frame, from: toVC.cancelImageView.superview)
191 | imageViewSnapshotPlay.frame = containerView.convert(toVC.playImageView.frame, from: toVC.playImageView.superview)
192 | imageViewSnapshotLike.frame = containerView.convert(toVC.likeImageView.frame, from: toVC.likeImageView.superview)
193 |
194 | imageViewSnapshotBackground.frame = containerView.convert(toVC.backgroundImageView.frame, from: toVC.backgroundImageView.superview)
195 |
196 |
197 | }
198 | }()
199 |
200 | // Animators
201 | let animator2 = {
202 | //UIViewPropertyAnimator(duration: 0.5, dampingRatio: 0.6) {
203 | UIViewPropertyAnimator(duration: 0.2, curve: .easeOut) {
204 | cellBackground.frame = frameBackground
205 | cellBackground.layer.cornerRadius = toVC.cellBackground.layer.cornerRadius
206 | }
207 | }()
208 |
209 |
210 |
211 |
212 | animator1.addCompletion { _ in
213 |
214 |
215 | cellBackground.removeFromSuperview()
216 | fromViewController.view.removeFromSuperview()
217 |
218 | titleLabel.removeFromSuperview()
219 | albumLabel.removeFromSuperview()
220 | yearLabel.removeFromSuperview()
221 |
222 | // TOP
223 | imageViewSnapshotProfile.removeFromSuperview()
224 | imageViewSnapshotPlus.removeFromSuperview()
225 | imageViewSnapshotBackground.removeFromSuperview()
226 |
227 | // BOTTOM
228 | imageViewSnapshotCancel.removeFromSuperview()
229 | imageViewSnapshotPlay.removeFromSuperview()
230 | imageViewSnapshotLike.removeFromSuperview()
231 |
232 |
233 | toViewController.view.isHidden = false
234 |
235 | transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
236 |
237 |
238 | }
239 |
240 |
241 | animator2.addCompletion { _ in
242 |
243 |
244 | cellBackground.removeFromSuperview()
245 | fromViewController.view.removeFromSuperview()
246 |
247 | titleLabel.removeFromSuperview()
248 | albumLabel.removeFromSuperview()
249 | yearLabel.removeFromSuperview()
250 |
251 | // TOP
252 | imageViewSnapshotProfile.removeFromSuperview()
253 | imageViewSnapshotPlus.removeFromSuperview()
254 | imageViewSnapshotBackground.removeFromSuperview()
255 |
256 | // BOTTOM
257 | imageViewSnapshotCancel.removeFromSuperview()
258 | imageViewSnapshotPlay.removeFromSuperview()
259 | imageViewSnapshotLike.removeFromSuperview()
260 |
261 | //toViewController.view.removeFromSuperview()
262 | fromViewController.view.removeFromSuperview()
263 |
264 | toViewController.view.isHidden = false
265 | transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
266 | //transitionContext.completeTransition(true)
267 | }
268 |
269 |
270 |
271 |
272 | func doBezierAnimation(showLayerAnimation: Bool = false) {
273 |
274 |
275 | //*** PROFILE IMAGE ***//
276 |
277 | // Main ImageView Animation
278 | var bezierPath = UIBezierPath()
279 | bezierPath.move(to: CGPoint(x: imageViewSnapshotProfile.frame.midX, y: imageViewSnapshotProfile.frame.midY))
280 | bezierPath.addQuadCurve(to: CGPoint(x: frameProfile.midX, y: frameProfile.midY), controlPoint: CGPoint(x: frameProfile.midX/2, y: frameProfile.midY/2))
281 |
282 |
283 | var shapeLayer = CAShapeLayer()
284 | // The Bezier path that we made needs to be converted to a CGPath before it can be used on a layer.
285 | shapeLayer.path = bezierPath.cgPath
286 | shapeLayer.strokeColor = UIColor.blue.cgColor
287 | shapeLayer.fillColor = UIColor.clear.cgColor
288 | shapeLayer.lineWidth = 1.0
289 |
290 | // Enable/Disable for debug
291 | if showLayerAnimation {
292 | containerView.layer.addSublayer(shapeLayer)
293 | }
294 |
295 | let profileAnimationPosition = CAKeyframeAnimation(keyPath: "position")
296 | profileAnimationPosition.path = bezierPath.cgPath
297 | // I set this one to make the animation go smoothly along the path
298 | profileAnimationPosition.calculationMode = kCAAnimationPaced
299 | profileAnimationPosition.duration = 0.4
300 | profileAnimationPosition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
301 |
302 |
303 | let profileAnimationBounds = CAKeyframeAnimation(keyPath: "bounds")
304 | profileAnimationBounds.duration = 0.4
305 | profileAnimationBounds.values = [imageViewSnapshotProfile.frame, containerView.convert(toVC.profileImageView.frame, from: toVC.profileImageView.superview)]
306 | profileAnimationBounds.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
307 | profileAnimationBounds.beginTime = 0
308 |
309 | // Let's group the animation for position and bounds into one
310 | let groupProfile = CAAnimationGroup()
311 | groupProfile.animations = [profileAnimationPosition, profileAnimationBounds]
312 | groupProfile.duration = 0.4
313 | groupProfile.repeatCount = 0
314 | groupProfile.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
315 | groupProfile.isRemovedOnCompletion = false
316 | groupProfile.fillMode = kCAFillModeForwards
317 |
318 | imageViewSnapshotProfile.layer.add(groupProfile, forKey: "profileAnimation")
319 |
320 |
321 | //*** PLUS IMAGE ***//
322 |
323 | // Plus ImageView Animation
324 | bezierPath = UIBezierPath()
325 | bezierPath.move(to: CGPoint(x: imageViewSnapshotPlus.frame.midX, y: imageViewSnapshotPlus.frame.midY))
326 | bezierPath.addQuadCurve(to: CGPoint(x: framePlus.midX, y: framePlus.midY), controlPoint: CGPoint(x:framePlus.maxX + 30, y: framePlus.maxY/4))
327 |
328 |
329 | shapeLayer = CAShapeLayer()
330 |
331 | // The Bezier path that we made needs to be converted to a CGPath before it can be used on a layer.
332 | shapeLayer.path = bezierPath.cgPath
333 | shapeLayer.strokeColor = UIColor.blue.cgColor
334 | shapeLayer.fillColor = UIColor.clear.cgColor
335 | shapeLayer.lineWidth = 1.0
336 |
337 | // Enable/Disable for debug
338 | if showLayerAnimation {
339 | containerView.layer.addSublayer(shapeLayer)
340 | }
341 |
342 |
343 |
344 | let plusAnimationPosition = CAKeyframeAnimation(keyPath: "position")
345 | plusAnimationPosition.path = bezierPath.cgPath
346 | // I set this one to make the animation go smoothly along the path
347 | plusAnimationPosition.calculationMode = kCAAnimationPaced
348 | plusAnimationPosition.duration = 0.4
349 | plusAnimationPosition.rotationMode = kCAAnimationLinear
350 | plusAnimationPosition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
351 |
352 |
353 | let plusAnimationBounds = CAKeyframeAnimation(keyPath: "bounds")
354 | plusAnimationBounds.duration = 0.4
355 | plusAnimationBounds.values = [imageViewSnapshotPlus.frame, containerView.convert(toVC.plusImageView.frame, from: toVC.plusImageView.superview)]
356 | plusAnimationBounds.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
357 | plusAnimationBounds.beginTime = 0
358 |
359 | // Let's group the animation for position and bounds into one
360 | let groupPlus = CAAnimationGroup()
361 | groupPlus.animations = [plusAnimationPosition, plusAnimationBounds]
362 | groupPlus.duration = 0.4
363 | groupPlus.repeatCount = 0
364 | groupPlus.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
365 | groupPlus.isRemovedOnCompletion = false
366 | groupPlus.fillMode = kCAFillModeForwards
367 |
368 | imageViewSnapshotPlus.layer.add(groupPlus, forKey: "doit")
369 |
370 |
371 |
372 |
373 | }
374 |
375 |
376 |
377 |
378 | animator1.startAnimation()
379 |
380 | // Group Animator
381 | doBezierAnimation(showLayerAnimation: false)
382 |
383 |
384 | }
385 |
386 |
387 | }
388 |
389 |
390 |
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Controllers/PushedViewController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
123 |
133 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
--------------------------------------------------------------------------------
/AnimationExampleAdvanced/Common/ViewControllerTransitions/PushAnimator.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import QuartzCore
3 |
4 |
5 | class PushAnimator: NSObject, UIViewControllerAnimatedTransitioning {
6 |
7 | var duration : TimeInterval
8 |
9 | init(duration : TimeInterval) {
10 | self.duration = duration
11 | }
12 |
13 | func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
14 | return duration
15 | }
16 |
17 | func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
18 |
19 | let containerView = transitionContext.containerView
20 |
21 |
22 | guard let fromVC = transitionContext.viewController(forKey: .from) as? animTransitionable,
23 | let toVC = transitionContext.viewController(forKey: .to) as? animTransitionable else {
24 | transitionContext.completeTransition(false)
25 | return
26 | }
27 |
28 |
29 |
30 |
31 | let fromViewController = transitionContext.viewController(forKey: .from)!
32 | let toViewController = transitionContext.viewController(forKey: .to)!
33 |
34 | // Plus Image
35 | let imageViewSnapshotPlus = UIImageView(image: fromVC.plusImageView.image)
36 | imageViewSnapshotPlus.contentMode = .scaleAspectFit
37 |
38 | //Profile Image
39 | let imageViewSnapshotProfile = UIImageView(image: fromVC.profileImageView.image)
40 | imageViewSnapshotProfile.contentMode = .scaleAspectFit
41 |
42 | //Background Image
43 | let imageViewSnapshotBackground = UIImageView(image: fromVC.backgroundImageView.image)
44 | imageViewSnapshotBackground.contentMode = .scaleAspectFit
45 |
46 |
47 | //Like Image
48 | let imageViewSnapshotLike = UIImageView(image: fromVC.likeImageView.image)
49 | imageViewSnapshotLike.contentMode = .scaleAspectFit
50 |
51 | //Play Image
52 | let imageViewSnapshotPlay = UIImageView(image: fromVC.playImageView.image)
53 | imageViewSnapshotPlay.contentMode = .scaleAspectFit
54 |
55 | //Cancel Image
56 | let imageViewSnapshotCancel = UIImageView(image: fromVC.cancelImageView.image)
57 | imageViewSnapshotCancel.contentMode = .scaleAspectFit
58 |
59 |
60 |
61 | //Background View With Correct Color
62 | let backgroundView = UIView()
63 | backgroundView.frame = fromVC.backgroundColor.frame
64 | backgroundView.backgroundColor = UIColor.white
65 | containerView.addSubview(backgroundView)
66 |
67 |
68 | // Title
69 | let titleLabel = duplicateLabel(label: fromVC.bigTitle)
70 | titleLabel.text = fromVC.bigTitle.text
71 | titleLabel.backgroundColor = UIColor.clear
72 | titleLabel.frame = containerView.convert(fromVC.bigTitle.frame, from: fromVC.bigTitle.superview)
73 |
74 | // Album
75 | let albumLabel = duplicateLabel(label: fromVC.albumLbl)
76 | albumLabel.text = fromVC.albumLbl.text
77 | albumLabel.backgroundColor = UIColor.clear
78 | albumLabel.frame = containerView.convert(fromVC.albumLbl.frame, from: fromVC.albumLbl.superview)
79 |
80 |
81 | // Year
82 | let yearLabel = duplicateLabel(label: fromVC.yearLbl)
83 | yearLabel.text = fromVC.yearLbl.text
84 | yearLabel.backgroundColor = UIColor.clear
85 | yearLabel.frame = containerView.convert(fromVC.yearLbl.frame, from: fromVC.yearLbl.superview)
86 |
87 |
88 |
89 |
90 | // Cell Background
91 | let cellBackground = UIView()
92 | cellBackground.frame = containerView.convert(fromVC.cellBackground.frame, from: fromVC.cellBackground.superview)
93 | cellBackground.backgroundColor = fromVC.cellBackground.backgroundColor
94 | cellBackground.layer.cornerRadius = fromVC.cellBackground.layer.cornerRadius
95 | cellBackground.layer.masksToBounds = fromVC.cellBackground.layer.masksToBounds
96 |
97 |
98 | containerView.addSubview(fromViewController.view)
99 | containerView.addSubview(toViewController.view)
100 |
101 | // Background Cell
102 | containerView.addSubview(cellBackground)
103 |
104 | // Top
105 | containerView.addSubview(imageViewSnapshotProfile)
106 | containerView.addSubview(imageViewSnapshotBackground)
107 | containerView.addSubview(imageViewSnapshotPlus)
108 |
109 | // Down
110 | containerView.addSubview(imageViewSnapshotPlay)
111 | containerView.addSubview(imageViewSnapshotCancel)
112 | containerView.addSubview(imageViewSnapshotLike)
113 |
114 |
115 | // Title Label
116 | containerView.addSubview(titleLabel)
117 | containerView.addSubview(albumLabel)
118 | containerView.addSubview(yearLabel)
119 |
120 | containerView.bringSubview(toFront: imageViewSnapshotPlus)
121 |
122 |
123 | fromViewController.view.isHidden = true
124 | toViewController.view.isHidden = true
125 |
126 | // TOP
127 | imageViewSnapshotPlus.frame = containerView.convert(fromVC.plusImageView.frame, from: fromVC.plusImageView.superview)
128 | imageViewSnapshotProfile.frame = containerView.convert(fromVC.profileImageView.frame, from: fromVC.profileImageView.superview)
129 | imageViewSnapshotBackground.frame = containerView.convert(fromVC.backgroundImageView.frame, from: fromVC.backgroundImageView.superview)
130 |
131 |
132 | // BOTTOM
133 | imageViewSnapshotCancel.frame = containerView.convert(fromVC.cancelImageView.frame, from: fromVC.cancelImageView.superview)
134 | imageViewSnapshotPlay.frame = containerView.convert(fromVC.playImageView.frame, from: fromVC.playImageView.superview)
135 | imageViewSnapshotLike.frame = containerView.convert(fromVC.likeImageView.frame, from: fromVC.likeImageView.superview)
136 |
137 |
138 |
139 |
140 | let frameBackground: CGRect = containerView.convert(toVC.backgroundColor.frame, from: toVC.backgroundColor.superview)
141 |
142 | // TOP
143 | let frameProfile: CGRect = containerView.convert(toVC.profileImageView.frame, from: toVC.profileImageView.superview)
144 | let frameBackgroundImage: CGRect = containerView.convert(toVC.backgroundImageView.frame, from: toVC.backgroundImageView.superview)
145 | let framePlus: CGRect = containerView.convert(toVC.plusImageView.frame, from: toVC.plusImageView.superview)
146 |
147 | // BOTTOM
148 | let framePlay: CGRect = containerView.convert(toVC.playImageView.frame, from: toVC.playImageView.superview)
149 |
150 |
151 | // Animators
152 | let animator1 = {
153 | UIViewPropertyAnimator(duration: 0.5, dampingRatio: 0.8) {
154 |
155 | // HAY QUE PONER BIEN LOS TAMAÑOS DE LAS IMAGENES
156 | let backgroundX = cellBackground.frame.minX + (cellBackground.frame.width * 5 / 100)
157 | let backgroundWidth = cellBackground.frame.width - (cellBackground.frame.width * 10 / 100)
158 |
159 |
160 | // BACKGROUND
161 | cellBackground.frame = CGRect(x: backgroundX , y: cellBackground.frame.minY + (cellBackground.frame.minY * 5 / 100), width: backgroundWidth, height: cellBackground.frame.height - (cellBackground.frame.height * 10 / 100))
162 |
163 | // LABEL
164 | titleLabel.transform = CGAffineTransform(scaleX: 0.8, y: 0.8)
165 | titleLabel.frame = CGRect(x: titleLabel.frame.minX , y: titleLabel.frame.minY + 15, width: titleLabel.frame.width, height: titleLabel.frame.height)
166 |
167 |
168 |
169 |
170 | // TOP
171 | imageViewSnapshotPlus.frame = CGRect(x: cellBackground.frame.maxX - (imageViewSnapshotPlus.frame.width * 20 / 100) - 40 , y: cellBackground.frame.minY + (imageViewSnapshotPlus.frame.height * 20 / 100) + 10, width: imageViewSnapshotPlus.frame.width - (imageViewSnapshotPlus.frame.width * 20 / 100), height: imageViewSnapshotPlus.frame.height - (imageViewSnapshotPlus.frame.height * 20 / 100))
172 |
173 |
174 | imageViewSnapshotProfile.frame = CGRect(x: cellBackground.frame.minX - (imageViewSnapshotProfile.frame.width * 20 / 100) + 30 , y: cellBackground.frame.minY + (imageViewSnapshotProfile.frame.height * 20 / 100) + 10, width: imageViewSnapshotProfile.frame.width - (imageViewSnapshotProfile.frame.width * 20 / 100), height: imageViewSnapshotProfile.frame.height - (imageViewSnapshotProfile.frame.height * 20 / 100))
175 |
176 | // LAbels
177 | albumLabel.frame = CGRect(x: imageViewSnapshotProfile.frame.maxX + 15 , y: imageViewSnapshotProfile.frame.minY + 3, width: albumLabel.frame.width, height: albumLabel.frame.height)
178 | albumLabel.sizeToFit()
179 |
180 | yearLabel.frame = CGRect(x: imageViewSnapshotProfile.frame.maxX + 15 , y: imageViewSnapshotProfile.frame.minY + 23, width: yearLabel.frame.width, height: yearLabel.frame.height)
181 | yearLabel.sizeToFit()
182 |
183 |
184 | // Image Background
185 | let widthBackground = (imageViewSnapshotBackground.frame.width - (imageViewSnapshotBackground.frame.width * 20 / 100) )
186 | let heightBackground = (imageViewSnapshotBackground.frame.height - (imageViewSnapshotBackground.frame.height * 20 / 100) )
187 | let midPostionPlayButton = imageViewSnapshotPlay.frame.width - (imageViewSnapshotPlay.frame.width * 20 / 100)
188 |
189 | imageViewSnapshotBackground.frame = CGRect(x: cellBackground.frame.midX - (widthBackground / 2) , y: cellBackground.frame.maxY - (heightBackground) , width: widthBackground, height: imageViewSnapshotBackground.frame.height - (imageViewSnapshotBackground.frame.height * 20 / 100))
190 |
191 |
192 |
193 | imageViewSnapshotPlay.frame = CGRect(x: cellBackground.frame.midX - (midPostionPlayButton / 2), y: cellBackground.frame.maxY - imageViewSnapshotPlay.frame.height - 10, width: imageViewSnapshotPlay.frame.width - (imageViewSnapshotPlay.frame.width * 20 / 100), height: imageViewSnapshotPlay.frame.width - (imageViewSnapshotPlay.frame.width * 20 / 100))
194 |
195 |
196 |
197 | imageViewSnapshotCancel.frame = CGRect(x: cellBackground.frame.midX - (midPostionPlayButton / 2) - imageViewSnapshotCancel.frame.width - 30, y: cellBackground.frame.maxY - (imageViewSnapshotCancel.frame.height * 2), width: imageViewSnapshotCancel.frame.width - (imageViewSnapshotCancel.frame.width * 20 / 100), height: imageViewSnapshotCancel.frame.height - (imageViewSnapshotCancel.frame.height * 20 / 100))
198 |
199 | imageViewSnapshotLike.frame = CGRect(x: cellBackground.frame.midX + (midPostionPlayButton / 2) + (imageViewSnapshotLike.frame.width * 20 / 100) + 30, y: cellBackground.frame.maxY - (imageViewSnapshotLike.frame.height * 2) , width: imageViewSnapshotLike.frame.width - (imageViewSnapshotLike.frame.width * 20 / 100), height: imageViewSnapshotLike.frame.height - (imageViewSnapshotLike.frame.height * 20 / 100))
200 |
201 |
202 |
203 | }
204 | }()
205 |
206 | // Animators
207 | let animator2 = {
208 | //UIViewPropertyAnimator(duration: 0.5, dampingRatio: 0.6) {
209 | UIViewPropertyAnimator(duration: 0.3, curve: .easeOut) {
210 |
211 | cellBackground.frame = CGRect(x: frameBackground.minX , y: frameBackground.minY, width: UIScreen.main.bounds.width, height: frameBackground.height)
212 | cellBackground.layer.cornerRadius = 0
213 |
214 | // Label
215 | titleLabel.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
216 | titleLabel.frame = containerView.convert(toVC.bigTitle.frame, from: toVC.bigTitle.superview)
217 |
218 | albumLabel.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
219 | albumLabel.frame = containerView.convert(toVC.albumLbl.frame, from: toVC.albumLbl.superview)
220 | albumLabel.textAlignment = .center
221 |
222 | yearLabel.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
223 | yearLabel.frame = containerView.convert(toVC.yearLbl.frame, from: toVC.yearLbl.superview)
224 | yearLabel.textAlignment = .center
225 |
226 |
227 | imageViewSnapshotCancel.frame = containerView.convert(toVC.cancelImageView.frame, from: toVC.cancelImageView.superview)
228 | imageViewSnapshotPlay.frame = containerView.convert(toVC.playImageView.frame, from: toVC.playImageView.superview)
229 | imageViewSnapshotLike.frame = containerView.convert(toVC.likeImageView.frame, from: toVC.likeImageView.superview)
230 |
231 | imageViewSnapshotBackground.frame = containerView.convert(toVC.backgroundImageView.frame, from: toVC.backgroundImageView.superview)
232 |
233 |
234 | cellBackground.layoutIfNeeded()
235 |
236 | }
237 | }()
238 |
239 |
240 |
241 | animator1.addCompletion { _ in
242 | animator2.startAnimation()
243 |
244 | // Group Animator
245 | doBezierAnimation(showLayerAnimation: false)
246 |
247 | }
248 |
249 |
250 | animator2.addCompletion { _ in
251 |
252 | // Background
253 | cellBackground.removeFromSuperview()
254 |
255 | // Labels
256 | titleLabel.removeFromSuperview()
257 | albumLabel.removeFromSuperview()
258 | yearLabel.removeFromSuperview()
259 |
260 | // TOP
261 | imageViewSnapshotProfile.removeFromSuperview()
262 | imageViewSnapshotPlus.removeFromSuperview()
263 | imageViewSnapshotBackground.removeFromSuperview()
264 |
265 | // BOTTOM
266 | imageViewSnapshotCancel.removeFromSuperview()
267 | imageViewSnapshotPlay.removeFromSuperview()
268 | imageViewSnapshotLike.removeFromSuperview()
269 |
270 | fromViewController.view.removeFromSuperview()
271 |
272 | toViewController.view.isHidden = false
273 |
274 | transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
275 |
276 |
277 | }
278 |
279 |
280 |
281 | animator1.startAnimation()
282 |
283 |
284 |
285 | func doBezierAnimation(showLayerAnimation: Bool = false) {
286 |
287 |
288 | //*** PROFILE IMAGE ***//
289 |
290 | // Profile Animation
291 | var bezierPath = UIBezierPath()
292 | bezierPath.move(to: CGPoint(x: imageViewSnapshotProfile.frame.midX, y: imageViewSnapshotProfile.frame.midY))
293 | bezierPath.addQuadCurve(to: CGPoint(x: UIScreen.main.bounds.width / 2 , y: frameProfile.midY), controlPoint: CGPoint(x: frameProfile.midX/2, y: frameProfile.midY/2))
294 |
295 |
296 | var shapeLayer = CAShapeLayer()
297 | // The Bezier path that we made needs to be converted to a CGPath before it can be used on a layer.
298 | shapeLayer.path = bezierPath.cgPath
299 | shapeLayer.strokeColor = UIColor.blue.cgColor
300 | shapeLayer.fillColor = UIColor.clear.cgColor
301 | shapeLayer.lineWidth = 1.0
302 |
303 | // Enable/Disable for debug
304 | if showLayerAnimation {
305 | containerView.layer.addSublayer(shapeLayer)
306 | }
307 |
308 | let profileAnimationPosition = CAKeyframeAnimation(keyPath: "position")
309 | profileAnimationPosition.path = bezierPath.cgPath
310 | // I set this one to make the animation go smoothly along the path
311 | profileAnimationPosition.calculationMode = kCAAnimationPaced
312 | profileAnimationPosition.duration = 0.3
313 | profileAnimationPosition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
314 |
315 |
316 | let profileAnimationBounds = CAKeyframeAnimation(keyPath: "bounds")
317 | profileAnimationBounds.duration = 0.3
318 | profileAnimationBounds.values = [imageViewSnapshotProfile.frame, containerView.convert(toVC.profileImageView.frame, from: toVC.profileImageView.superview)]
319 | profileAnimationBounds.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
320 | profileAnimationBounds.beginTime = 0
321 |
322 | // Let's group the animation for position and bounds into one
323 | let groupProfile = CAAnimationGroup()
324 | groupProfile.animations = [profileAnimationPosition, profileAnimationBounds]
325 | groupProfile.duration = 0.3
326 | groupProfile.repeatCount = 0
327 | groupProfile.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
328 | groupProfile.isRemovedOnCompletion = false
329 | groupProfile.fillMode = kCAFillModeForwards
330 |
331 | imageViewSnapshotProfile.layer.add(groupProfile, forKey: "profileAnimation")
332 |
333 |
334 | //*** PLUS IMAGE ***//
335 |
336 | // Plus ImageView Animation
337 | bezierPath = UIBezierPath()
338 | bezierPath.move(to: CGPoint(x: imageViewSnapshotPlus.frame.maxX, y: imageViewSnapshotPlus.frame.maxY))
339 | bezierPath.addQuadCurve(to: CGPoint(x: (UIScreen.main.bounds.width / 2) + 20, y: framePlus.maxY - 10), controlPoint: CGPoint(x:framePlus.maxX + 30, y: framePlus.maxY/4))
340 |
341 |
342 | shapeLayer = CAShapeLayer()
343 |
344 | // The Bezier path that we made needs to be converted to
345 | shapeLayer.path = bezierPath.cgPath
346 | shapeLayer.strokeColor = UIColor.blue.cgColor
347 | shapeLayer.fillColor = UIColor.clear.cgColor
348 | shapeLayer.lineWidth = 1.0
349 |
350 | // Enable/Disable for debug
351 | if showLayerAnimation {
352 | containerView.layer.addSublayer(shapeLayer)
353 | }
354 |
355 |
356 |
357 | let plusAnimationPosition = CAKeyframeAnimation(keyPath: "position")
358 | plusAnimationPosition.path = bezierPath.cgPath
359 | // I set this one to make the animation go smoothly along the path
360 | plusAnimationPosition.calculationMode = kCAAnimationPaced
361 | plusAnimationPosition.duration = 0.3
362 | plusAnimationPosition.rotationMode = kCAAnimationLinear
363 | plusAnimationPosition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
364 |
365 |
366 | let plusAnimationBounds = CAKeyframeAnimation(keyPath: "bounds")
367 | plusAnimationBounds.duration = 0.3
368 | plusAnimationBounds.values = [imageViewSnapshotPlus.frame, containerView.convert(toVC.plusImageView.frame, from: toVC.plusImageView.superview)]
369 | plusAnimationBounds.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
370 | plusAnimationBounds.beginTime = 0
371 |
372 | // Let's group the animation for position and bounds into one
373 | let groupPlus = CAAnimationGroup()
374 | groupPlus.animations = [plusAnimationPosition, plusAnimationBounds]
375 | groupPlus.duration = 0.3
376 | groupPlus.repeatCount = 0
377 | groupPlus.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
378 | groupPlus.isRemovedOnCompletion = false
379 | groupPlus.fillMode = kCAFillModeForwards
380 |
381 | imageViewSnapshotPlus.layer.add(groupPlus, forKey: "doit")
382 |
383 |
384 | }
385 |
386 | }
387 |
388 |
389 |
390 | }
391 |
392 |
393 |
--------------------------------------------------------------------------------
/AnimationExampleAdvanced.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 81BCA8C021510B1000CA0E66 /* MainTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81BCA8BE21510B1000CA0E66 /* MainTableViewCell.swift */; };
11 | 81BCA8C121510B1000CA0E66 /* MainTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 81BCA8BF21510B1000CA0E66 /* MainTableViewCell.xib */; };
12 | A10ACF5A22F4BF28001640A0 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = A10ACF5922F4BF28001640A0 /* README.md */; };
13 | A10ACF6622F4C6B4001640A0 /* TransitionCordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A10ACF6522F4C6B4001640A0 /* TransitionCordinator.swift */; };
14 | A10ACF6822F4DBCF001640A0 /* MainViewController+DataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = A10ACF6722F4DBCF001640A0 /* MainViewController+DataSource.swift */; };
15 | A10ACF6A22F4DC14001640A0 /* MainViewController+ProtocolTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = A10ACF6922F4DC14001640A0 /* MainViewController+ProtocolTransition.swift */; };
16 | A19C21A021471E8600CDC6ED /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A19C219F21471E8600CDC6ED /* AppDelegate.swift */; };
17 | A19C21A221471E8600CDC6ED /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A19C21A121471E8600CDC6ED /* ViewController.swift */; };
18 | A19C21A521471E8600CDC6ED /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A19C21A321471E8600CDC6ED /* Main.storyboard */; };
19 | A19C21A721471E9100CDC6ED /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A19C21A621471E9100CDC6ED /* Assets.xcassets */; };
20 | A19C21AA21471E9100CDC6ED /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A19C21A821471E9100CDC6ED /* LaunchScreen.storyboard */; };
21 | A19C21B921471FCB00CDC6ED /* MainViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = A19C21B121471FCB00CDC6ED /* MainViewController.xib */; };
22 | A19C21BC21471FCB00CDC6ED /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A19C21B521471FCB00CDC6ED /* MainViewController.swift */; };
23 | A19C21C321474D5800CDC6ED /* PushedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A19C21C121474D5800CDC6ED /* PushedViewController.swift */; };
24 | A19C21C421474D5800CDC6ED /* PushedViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = A19C21C221474D5800CDC6ED /* PushedViewController.xib */; };
25 | A19C21C621474F6400CDC6ED /* PopAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A19C21C521474F6400CDC6ED /* PopAnimator.swift */; };
26 | A19C21C82149F14F00CDC6ED /* PushAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A19C21C72149F14F00CDC6ED /* PushAnimator.swift */; };
27 | A19C21CA2149F16200CDC6ED /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = A19C21C92149F16200CDC6ED /* Helpers.swift */; };
28 | /* End PBXBuildFile section */
29 |
30 | /* Begin PBXFileReference section */
31 | 81BCA8BE21510B1000CA0E66 /* MainTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainTableViewCell.swift; sourceTree = ""; };
32 | 81BCA8BF21510B1000CA0E66 /* MainTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainTableViewCell.xib; sourceTree = ""; };
33 | A10ACF5922F4BF28001640A0 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; };
34 | A10ACF6522F4C6B4001640A0 /* TransitionCordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransitionCordinator.swift; sourceTree = ""; };
35 | A10ACF6722F4DBCF001640A0 /* MainViewController+DataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MainViewController+DataSource.swift"; sourceTree = ""; };
36 | A10ACF6922F4DC14001640A0 /* MainViewController+ProtocolTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MainViewController+ProtocolTransition.swift"; sourceTree = ""; };
37 | A19C219C21471E8600CDC6ED /* AnimationExampleAdvanced.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AnimationExampleAdvanced.app; sourceTree = BUILT_PRODUCTS_DIR; };
38 | A19C219F21471E8600CDC6ED /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
39 | A19C21A121471E8600CDC6ED /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
40 | A19C21A421471E8600CDC6ED /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
41 | A19C21A621471E9100CDC6ED /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
42 | A19C21A921471E9100CDC6ED /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
43 | A19C21AB21471E9100CDC6ED /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
44 | A19C21B121471FCB00CDC6ED /* MainViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainViewController.xib; sourceTree = ""; };
45 | A19C21B521471FCB00CDC6ED /* MainViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = ""; };
46 | A19C21C121474D5800CDC6ED /* PushedViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PushedViewController.swift; sourceTree = ""; };
47 | A19C21C221474D5800CDC6ED /* PushedViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PushedViewController.xib; sourceTree = ""; };
48 | A19C21C521474F6400CDC6ED /* PopAnimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PopAnimator.swift; sourceTree = ""; };
49 | A19C21C72149F14F00CDC6ED /* PushAnimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PushAnimator.swift; sourceTree = ""; };
50 | A19C21C92149F16200CDC6ED /* Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Helpers.swift; sourceTree = ""; };
51 | /* End PBXFileReference section */
52 |
53 | /* Begin PBXFrameworksBuildPhase section */
54 | A19C219921471E8600CDC6ED /* Frameworks */ = {
55 | isa = PBXFrameworksBuildPhase;
56 | buildActionMask = 2147483647;
57 | files = (
58 | );
59 | runOnlyForDeploymentPostprocessing = 0;
60 | };
61 | /* End PBXFrameworksBuildPhase section */
62 |
63 | /* Begin PBXGroup section */
64 | A10ACF5B22F4BF30001640A0 /* Models */ = {
65 | isa = PBXGroup;
66 | children = (
67 | );
68 | path = Models;
69 | sourceTree = "";
70 | };
71 | A10ACF5C22F4BF3F001640A0 /* ViewModels */ = {
72 | isa = PBXGroup;
73 | children = (
74 | );
75 | path = ViewModels;
76 | sourceTree = "";
77 | };
78 | A10ACF5D22F4BF46001640A0 /* Views */ = {
79 | isa = PBXGroup;
80 | children = (
81 | A10ACF5E22F4BF4C001640A0 /* Cells */,
82 | );
83 | path = Views;
84 | sourceTree = "";
85 | };
86 | A10ACF5E22F4BF4C001640A0 /* Cells */ = {
87 | isa = PBXGroup;
88 | children = (
89 | 81BCA8BF21510B1000CA0E66 /* MainTableViewCell.xib */,
90 | 81BCA8BE21510B1000CA0E66 /* MainTableViewCell.swift */,
91 | );
92 | path = Cells;
93 | sourceTree = "";
94 | };
95 | A10ACF5F22F4BF53001640A0 /* Controllers */ = {
96 | isa = PBXGroup;
97 | children = (
98 | A19C21B521471FCB00CDC6ED /* MainViewController.swift */,
99 | A10ACF6722F4DBCF001640A0 /* MainViewController+DataSource.swift */,
100 | A10ACF6922F4DC14001640A0 /* MainViewController+ProtocolTransition.swift */,
101 | A19C21B121471FCB00CDC6ED /* MainViewController.xib */,
102 | A19C21C121474D5800CDC6ED /* PushedViewController.swift */,
103 | A19C21C221474D5800CDC6ED /* PushedViewController.xib */,
104 | );
105 | path = Controllers;
106 | sourceTree = "";
107 | };
108 | A10ACF6022F4BF66001640A0 /* Helpers */ = {
109 | isa = PBXGroup;
110 | children = (
111 | A19C21C92149F16200CDC6ED /* Helpers.swift */,
112 | );
113 | path = Helpers;
114 | sourceTree = "";
115 | };
116 | A10ACF6122F4BF72001640A0 /* Common */ = {
117 | isa = PBXGroup;
118 | children = (
119 | A10ACF6222F4BF78001640A0 /* ViewControllerTransitions */,
120 | A10ACF6322F4C418001640A0 /* Navigation */,
121 | );
122 | path = Common;
123 | sourceTree = "";
124 | };
125 | A10ACF6222F4BF78001640A0 /* ViewControllerTransitions */ = {
126 | isa = PBXGroup;
127 | children = (
128 | A19C21C72149F14F00CDC6ED /* PushAnimator.swift */,
129 | A19C21C521474F6400CDC6ED /* PopAnimator.swift */,
130 | );
131 | path = ViewControllerTransitions;
132 | sourceTree = "";
133 | };
134 | A10ACF6322F4C418001640A0 /* Navigation */ = {
135 | isa = PBXGroup;
136 | children = (
137 | A10ACF6522F4C6B4001640A0 /* TransitionCordinator.swift */,
138 | );
139 | path = Navigation;
140 | sourceTree = "";
141 | };
142 | A19C219321471E8600CDC6ED = {
143 | isa = PBXGroup;
144 | children = (
145 | A19C219E21471E8600CDC6ED /* AnimationExampleAdvanced */,
146 | A19C219D21471E8600CDC6ED /* Products */,
147 | );
148 | sourceTree = "";
149 | };
150 | A19C219D21471E8600CDC6ED /* Products */ = {
151 | isa = PBXGroup;
152 | children = (
153 | A19C219C21471E8600CDC6ED /* AnimationExampleAdvanced.app */,
154 | );
155 | name = Products;
156 | sourceTree = "";
157 | };
158 | A19C219E21471E8600CDC6ED /* AnimationExampleAdvanced */ = {
159 | isa = PBXGroup;
160 | children = (
161 | A10ACF5922F4BF28001640A0 /* README.md */,
162 | A10ACF5B22F4BF30001640A0 /* Models */,
163 | A10ACF5C22F4BF3F001640A0 /* ViewModels */,
164 | A10ACF5D22F4BF46001640A0 /* Views */,
165 | A10ACF5F22F4BF53001640A0 /* Controllers */,
166 | A10ACF6022F4BF66001640A0 /* Helpers */,
167 | A10ACF6122F4BF72001640A0 /* Common */,
168 | A19C219F21471E8600CDC6ED /* AppDelegate.swift */,
169 | A19C21A121471E8600CDC6ED /* ViewController.swift */,
170 | A19C21A321471E8600CDC6ED /* Main.storyboard */,
171 | A19C21A621471E9100CDC6ED /* Assets.xcassets */,
172 | A19C21A821471E9100CDC6ED /* LaunchScreen.storyboard */,
173 | A19C21AB21471E9100CDC6ED /* Info.plist */,
174 | );
175 | path = AnimationExampleAdvanced;
176 | sourceTree = "";
177 | };
178 | /* End PBXGroup section */
179 |
180 | /* Begin PBXNativeTarget section */
181 | A19C219B21471E8600CDC6ED /* AnimationExampleAdvanced */ = {
182 | isa = PBXNativeTarget;
183 | buildConfigurationList = A19C21AE21471E9100CDC6ED /* Build configuration list for PBXNativeTarget "AnimationExampleAdvanced" */;
184 | buildPhases = (
185 | A19C219821471E8600CDC6ED /* Sources */,
186 | A19C219921471E8600CDC6ED /* Frameworks */,
187 | A19C219A21471E8600CDC6ED /* Resources */,
188 | );
189 | buildRules = (
190 | );
191 | dependencies = (
192 | );
193 | name = AnimationExampleAdvanced;
194 | productName = AnimationExample;
195 | productReference = A19C219C21471E8600CDC6ED /* AnimationExampleAdvanced.app */;
196 | productType = "com.apple.product-type.application";
197 | };
198 | /* End PBXNativeTarget section */
199 |
200 | /* Begin PBXProject section */
201 | A19C219421471E8600CDC6ED /* Project object */ = {
202 | isa = PBXProject;
203 | attributes = {
204 | LastSwiftUpdateCheck = 0930;
205 | LastUpgradeCheck = 0930;
206 | ORGANIZATIONNAME = "Francisco Obarrio";
207 | TargetAttributes = {
208 | A19C219B21471E8600CDC6ED = {
209 | CreatedOnToolsVersion = 9.3;
210 | };
211 | };
212 | };
213 | buildConfigurationList = A19C219721471E8600CDC6ED /* Build configuration list for PBXProject "AnimationExampleAdvanced" */;
214 | compatibilityVersion = "Xcode 9.3";
215 | developmentRegion = en;
216 | hasScannedForEncodings = 0;
217 | knownRegions = (
218 | en,
219 | Base,
220 | );
221 | mainGroup = A19C219321471E8600CDC6ED;
222 | productRefGroup = A19C219D21471E8600CDC6ED /* Products */;
223 | projectDirPath = "";
224 | projectRoot = "";
225 | targets = (
226 | A19C219B21471E8600CDC6ED /* AnimationExampleAdvanced */,
227 | );
228 | };
229 | /* End PBXProject section */
230 |
231 | /* Begin PBXResourcesBuildPhase section */
232 | A19C219A21471E8600CDC6ED /* Resources */ = {
233 | isa = PBXResourcesBuildPhase;
234 | buildActionMask = 2147483647;
235 | files = (
236 | A19C21AA21471E9100CDC6ED /* LaunchScreen.storyboard in Resources */,
237 | A19C21A721471E9100CDC6ED /* Assets.xcassets in Resources */,
238 | A19C21B921471FCB00CDC6ED /* MainViewController.xib in Resources */,
239 | A10ACF5A22F4BF28001640A0 /* README.md in Resources */,
240 | 81BCA8C121510B1000CA0E66 /* MainTableViewCell.xib in Resources */,
241 | A19C21A521471E8600CDC6ED /* Main.storyboard in Resources */,
242 | A19C21C421474D5800CDC6ED /* PushedViewController.xib in Resources */,
243 | );
244 | runOnlyForDeploymentPostprocessing = 0;
245 | };
246 | /* End PBXResourcesBuildPhase section */
247 |
248 | /* Begin PBXSourcesBuildPhase section */
249 | A19C219821471E8600CDC6ED /* Sources */ = {
250 | isa = PBXSourcesBuildPhase;
251 | buildActionMask = 2147483647;
252 | files = (
253 | A19C21BC21471FCB00CDC6ED /* MainViewController.swift in Sources */,
254 | A19C21C621474F6400CDC6ED /* PopAnimator.swift in Sources */,
255 | A10ACF6A22F4DC14001640A0 /* MainViewController+ProtocolTransition.swift in Sources */,
256 | A19C21CA2149F16200CDC6ED /* Helpers.swift in Sources */,
257 | A10ACF6622F4C6B4001640A0 /* TransitionCordinator.swift in Sources */,
258 | 81BCA8C021510B1000CA0E66 /* MainTableViewCell.swift in Sources */,
259 | A19C21A221471E8600CDC6ED /* ViewController.swift in Sources */,
260 | A19C21C321474D5800CDC6ED /* PushedViewController.swift in Sources */,
261 | A19C21C82149F14F00CDC6ED /* PushAnimator.swift in Sources */,
262 | A19C21A021471E8600CDC6ED /* AppDelegate.swift in Sources */,
263 | A10ACF6822F4DBCF001640A0 /* MainViewController+DataSource.swift in Sources */,
264 | );
265 | runOnlyForDeploymentPostprocessing = 0;
266 | };
267 | /* End PBXSourcesBuildPhase section */
268 |
269 | /* Begin PBXVariantGroup section */
270 | A19C21A321471E8600CDC6ED /* Main.storyboard */ = {
271 | isa = PBXVariantGroup;
272 | children = (
273 | A19C21A421471E8600CDC6ED /* Base */,
274 | );
275 | name = Main.storyboard;
276 | sourceTree = "";
277 | };
278 | A19C21A821471E9100CDC6ED /* LaunchScreen.storyboard */ = {
279 | isa = PBXVariantGroup;
280 | children = (
281 | A19C21A921471E9100CDC6ED /* Base */,
282 | );
283 | name = LaunchScreen.storyboard;
284 | sourceTree = "";
285 | };
286 | /* End PBXVariantGroup section */
287 |
288 | /* Begin XCBuildConfiguration section */
289 | A19C21AC21471E9100CDC6ED /* Debug */ = {
290 | isa = XCBuildConfiguration;
291 | buildSettings = {
292 | ALWAYS_SEARCH_USER_PATHS = NO;
293 | CLANG_ANALYZER_NONNULL = YES;
294 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
295 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
296 | CLANG_CXX_LIBRARY = "libc++";
297 | CLANG_ENABLE_MODULES = YES;
298 | CLANG_ENABLE_OBJC_ARC = YES;
299 | CLANG_ENABLE_OBJC_WEAK = YES;
300 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
301 | CLANG_WARN_BOOL_CONVERSION = YES;
302 | CLANG_WARN_COMMA = YES;
303 | CLANG_WARN_CONSTANT_CONVERSION = YES;
304 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
305 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
306 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
307 | CLANG_WARN_EMPTY_BODY = YES;
308 | CLANG_WARN_ENUM_CONVERSION = YES;
309 | CLANG_WARN_INFINITE_RECURSION = YES;
310 | CLANG_WARN_INT_CONVERSION = YES;
311 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
312 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
313 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
314 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
315 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
316 | CLANG_WARN_STRICT_PROTOTYPES = YES;
317 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
318 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
319 | CLANG_WARN_UNREACHABLE_CODE = YES;
320 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
321 | CODE_SIGN_IDENTITY = "iPhone Developer";
322 | COPY_PHASE_STRIP = NO;
323 | DEBUG_INFORMATION_FORMAT = dwarf;
324 | ENABLE_STRICT_OBJC_MSGSEND = YES;
325 | ENABLE_TESTABILITY = YES;
326 | GCC_C_LANGUAGE_STANDARD = gnu11;
327 | GCC_DYNAMIC_NO_PIC = NO;
328 | GCC_NO_COMMON_BLOCKS = YES;
329 | GCC_OPTIMIZATION_LEVEL = 0;
330 | GCC_PREPROCESSOR_DEFINITIONS = (
331 | "DEBUG=1",
332 | "$(inherited)",
333 | );
334 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
335 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
336 | GCC_WARN_UNDECLARED_SELECTOR = YES;
337 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
338 | GCC_WARN_UNUSED_FUNCTION = YES;
339 | GCC_WARN_UNUSED_VARIABLE = YES;
340 | IPHONEOS_DEPLOYMENT_TARGET = 11.3;
341 | MTL_ENABLE_DEBUG_INFO = YES;
342 | ONLY_ACTIVE_ARCH = YES;
343 | SDKROOT = iphoneos;
344 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
345 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
346 | };
347 | name = Debug;
348 | };
349 | A19C21AD21471E9100CDC6ED /* Release */ = {
350 | isa = XCBuildConfiguration;
351 | buildSettings = {
352 | ALWAYS_SEARCH_USER_PATHS = NO;
353 | CLANG_ANALYZER_NONNULL = YES;
354 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
355 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
356 | CLANG_CXX_LIBRARY = "libc++";
357 | CLANG_ENABLE_MODULES = YES;
358 | CLANG_ENABLE_OBJC_ARC = YES;
359 | CLANG_ENABLE_OBJC_WEAK = YES;
360 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
361 | CLANG_WARN_BOOL_CONVERSION = YES;
362 | CLANG_WARN_COMMA = YES;
363 | CLANG_WARN_CONSTANT_CONVERSION = YES;
364 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
365 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
366 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
367 | CLANG_WARN_EMPTY_BODY = YES;
368 | CLANG_WARN_ENUM_CONVERSION = YES;
369 | CLANG_WARN_INFINITE_RECURSION = YES;
370 | CLANG_WARN_INT_CONVERSION = YES;
371 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
372 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
373 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
374 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
375 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
376 | CLANG_WARN_STRICT_PROTOTYPES = YES;
377 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
378 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
379 | CLANG_WARN_UNREACHABLE_CODE = YES;
380 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
381 | CODE_SIGN_IDENTITY = "iPhone Developer";
382 | COPY_PHASE_STRIP = NO;
383 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
384 | ENABLE_NS_ASSERTIONS = NO;
385 | ENABLE_STRICT_OBJC_MSGSEND = YES;
386 | GCC_C_LANGUAGE_STANDARD = gnu11;
387 | GCC_NO_COMMON_BLOCKS = YES;
388 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
389 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
390 | GCC_WARN_UNDECLARED_SELECTOR = YES;
391 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
392 | GCC_WARN_UNUSED_FUNCTION = YES;
393 | GCC_WARN_UNUSED_VARIABLE = YES;
394 | IPHONEOS_DEPLOYMENT_TARGET = 11.3;
395 | MTL_ENABLE_DEBUG_INFO = NO;
396 | SDKROOT = iphoneos;
397 | SWIFT_COMPILATION_MODE = wholemodule;
398 | SWIFT_OPTIMIZATION_LEVEL = "-O";
399 | VALIDATE_PRODUCT = YES;
400 | };
401 | name = Release;
402 | };
403 | A19C21AF21471E9100CDC6ED /* Debug */ = {
404 | isa = XCBuildConfiguration;
405 | buildSettings = {
406 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
407 | CODE_SIGN_IDENTITY = "iPhone Developer";
408 | CODE_SIGN_STYLE = Automatic;
409 | DEVELOPMENT_TEAM = E8FV83GSJC;
410 | INFOPLIST_FILE = AnimationExampleAdvanced/Info.plist;
411 | LD_RUNPATH_SEARCH_PATHS = (
412 | "$(inherited)",
413 | "@executable_path/Frameworks",
414 | );
415 | PRODUCT_BUNDLE_IDENTIFIER = com.franobarrio.AnimationAdvanced;
416 | PRODUCT_NAME = "$(TARGET_NAME)";
417 | PROVISIONING_PROFILE = "";
418 | PROVISIONING_PROFILE_SPECIFIER = "";
419 | SWIFT_VERSION = 4.0;
420 | TARGETED_DEVICE_FAMILY = "1,2";
421 | };
422 | name = Debug;
423 | };
424 | A19C21B021471E9100CDC6ED /* Release */ = {
425 | isa = XCBuildConfiguration;
426 | buildSettings = {
427 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
428 | CODE_SIGN_IDENTITY = "iPhone Developer";
429 | CODE_SIGN_STYLE = Automatic;
430 | DEVELOPMENT_TEAM = E8FV83GSJC;
431 | INFOPLIST_FILE = AnimationExampleAdvanced/Info.plist;
432 | LD_RUNPATH_SEARCH_PATHS = (
433 | "$(inherited)",
434 | "@executable_path/Frameworks",
435 | );
436 | PRODUCT_BUNDLE_IDENTIFIER = com.franobarrio.AnimationAdvanced;
437 | PRODUCT_NAME = "$(TARGET_NAME)";
438 | PROVISIONING_PROFILE_SPECIFIER = "";
439 | SWIFT_VERSION = 4.0;
440 | TARGETED_DEVICE_FAMILY = "1,2";
441 | };
442 | name = Release;
443 | };
444 | /* End XCBuildConfiguration section */
445 |
446 | /* Begin XCConfigurationList section */
447 | A19C219721471E8600CDC6ED /* Build configuration list for PBXProject "AnimationExampleAdvanced" */ = {
448 | isa = XCConfigurationList;
449 | buildConfigurations = (
450 | A19C21AC21471E9100CDC6ED /* Debug */,
451 | A19C21AD21471E9100CDC6ED /* Release */,
452 | );
453 | defaultConfigurationIsVisible = 0;
454 | defaultConfigurationName = Release;
455 | };
456 | A19C21AE21471E9100CDC6ED /* Build configuration list for PBXNativeTarget "AnimationExampleAdvanced" */ = {
457 | isa = XCConfigurationList;
458 | buildConfigurations = (
459 | A19C21AF21471E9100CDC6ED /* Debug */,
460 | A19C21B021471E9100CDC6ED /* Release */,
461 | );
462 | defaultConfigurationIsVisible = 0;
463 | defaultConfigurationName = Release;
464 | };
465 | /* End XCConfigurationList section */
466 | };
467 | rootObject = A19C219421471E8600CDC6ED /* Project object */;
468 | }
469 |
--------------------------------------------------------------------------------