├── .gitignore
├── Demo
├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ └── Contents.json
│ ├── Contents.json
│ └── test.imageset
│ │ ├── Contents.json
│ │ └── test.png
├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── Demo.xcodeproj
│ ├── project.pbxproj
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Demo.xcscheme
├── Info.plist
├── MDAppDelegate.h
├── MDAppDelegate.m
├── MDCustomImageViewController.h
├── MDCustomImageViewController.m
├── MDCustomViewController.h
├── MDCustomViewController.m
├── MDPresentedViewController.h
├── MDPresentedViewController.m
├── MDPresentionControlViewController.h
├── MDPresentionControlViewController.m
├── MDRootViewController.h
├── MDRootViewController.m
├── MDVerticalSwipPopViewController.h
├── MDVerticalSwipPopViewController.m
└── main.m
├── ImagePreview
├── MDImageDismissInteractionController.h
├── MDImageDismissInteractionController.m
├── MDImageDraggingDismissInteractionController.h
├── MDImageDraggingDismissInteractionController.m
├── MDImageViewController.h
├── MDImageViewController.m
├── MDImageZoomAnimationController.h
├── MDImageZoomAnimationController.m
└── MDTransitioning+ImagePreview.h
├── Info.plist
├── LICENSE
├── MDTransitioning.md
├── MDTransitioning.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
└── xcshareddata
│ └── xcschemes
│ ├── MDTransitioning.xcscheme
│ └── MDTransitioning_ImagePriview.xcscheme
├── MDTransitioning.xcworkspace
├── contents.xcworkspacedata
└── xcshareddata
│ └── IDEWorkspaceChecks.plist
├── MDTransitioning
├── MDAnimatedTransitioning.h
├── MDInteractionController.h
├── MDInteractiveTransitioning.h
├── MDNavigationAnimationController.h
├── MDNavigationAnimationController.m
├── MDNavigationControllerDelegate.h
├── MDNavigationControllerDelegate.m
├── MDPopInteractionController.h
├── MDPopInteractionController.m
├── MDPresentionAnimationController.h
├── MDPresentionAnimationController.m
├── MDPresentionControllerDelegate.h
├── MDPresentionControllerDelegate.m
├── MDScaleNavigationAnimationController.h
├── MDScaleNavigationAnimationController.m
├── MDSwipeInteractionController.h
├── MDSwipeInteractionController.m
├── MDTransitioning+Private.h
├── MDTransitioning+Private.m
├── MDTransitioning.h
├── MDVerticalSwipDismissInteractionController.h
├── MDVerticalSwipDismissInteractionController.m
├── MDVerticalSwipInteractionController.h
├── MDVerticalSwipInteractionController.m
├── MDVerticalSwipPopInteractionController.h
├── MDVerticalSwipPopInteractionController.m
├── UIViewController+MDNavigationTransitioning.h
├── UIViewController+MDNavigationTransitioning.m
├── UIViewController+MDPresentionTransitioning.h
└── UIViewController+MDPresentionTransitioning.m
├── README.md
└── snapshots
├── custom_present.gif
├── custom_push.gif
├── image_present.gif
├── scale_push.gif
├── system_present.gif
├── system_push.gif
└── vertical_pop.gif
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 |
20 | ## Other
21 | *.moved-aside
22 | *.xccheckout
23 | *.xcscmblueprint
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 | *.ipa
28 | *.dSYM.zip
29 | *.dSYM
30 |
31 | # CocoaPods
32 | #
33 | # We recommend against adding the Pods directory to your .gitignore. However
34 | # you should judge for yourself, the pros and cons are mentioned at:
35 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
36 | #
37 | # Pods/
38 |
39 | # Carthage
40 | #
41 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
42 | # Carthage/Checkouts
43 |
44 | Carthage/Build
45 |
46 | # fastlane
47 | #
48 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
49 | # screenshots whenever they are needed.
50 | # For more information about the recommended setup visit:
51 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
52 |
53 | fastlane/report.xml
54 | fastlane/Preview.html
55 | fastlane/screenshots
56 | fastlane/test_output
57 |
58 | # Code Injection
59 | #
60 | # After new code Injection tools there's a generated folder /iOSInjectionProject
61 | # https://github.com/johnno1962/injectionforxcode
62 |
63 | iOSInjectionProject/
64 |
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | }
88 | ],
89 | "info" : {
90 | "version" : 1,
91 | "author" : "xcode"
92 | }
93 | }
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/test.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "test.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 | }
--------------------------------------------------------------------------------
/Demo/Assets.xcassets/test.imageset/test.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Modool/MDTransitioning/d2f6ee1b9cbcc4e59d2108d27612cad540198542/Demo/Assets.xcassets/test.imageset/test.png
--------------------------------------------------------------------------------
/Demo/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 |
27 |
28 |
--------------------------------------------------------------------------------
/Demo/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 |
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 |
86 |
94 |
102 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
139 |
147 |
155 |
156 |
157 |
158 |
159 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
--------------------------------------------------------------------------------
/Demo/Demo.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 083D02191F3057F400D1E530 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 083D020B1F3057F400D1E530 /* Assets.xcassets */; };
11 | 083D021A1F3057F400D1E530 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 083D020D1F3057F400D1E530 /* LaunchScreen.storyboard */; };
12 | 083D021B1F3057F400D1E530 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 083D020F1F3057F400D1E530 /* Main.storyboard */; };
13 | 083D021D1F3057F400D1E530 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 083D02121F3057F400D1E530 /* main.m */; };
14 | 083D021E1F3057F400D1E530 /* MDAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 083D02141F3057F400D1E530 /* MDAppDelegate.m */; };
15 | 083D021F1F3057F400D1E530 /* MDPresentedViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 083D02161F3057F400D1E530 /* MDPresentedViewController.m */; };
16 | 083D02201F3057F400D1E530 /* MDPresentionControlViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 083D02181F3057F400D1E530 /* MDPresentionControlViewController.m */; };
17 | 083D02311F30626D00D1E530 /* MDCustomViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 083D02301F30626D00D1E530 /* MDCustomViewController.m */; };
18 | 08555F3D1F31775600591B10 /* MDTransitioning.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08555F3C1F31775600591B10 /* MDTransitioning.framework */; };
19 | 08555F3E1F31775600591B10 /* MDTransitioning.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 08555F3C1F31775600591B10 /* MDTransitioning.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
20 | 08555F401F31775600591B10 /* MDTransitioning_ImagePriview.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08555F3F1F31775600591B10 /* MDTransitioning_ImagePriview.framework */; };
21 | 08555F411F31775600591B10 /* MDTransitioning_ImagePriview.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 08555F3F1F31775600591B10 /* MDTransitioning_ImagePriview.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
22 | 0856B4AA1F72CBDE00905F3A /* MDCustomImageViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0856B4A91F72CBDE00905F3A /* MDCustomImageViewController.m */; };
23 | 0856B4AD1F72D06300905F3A /* MDVerticalSwipPopViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0856B4AC1F72D06300905F3A /* MDVerticalSwipPopViewController.m */; };
24 | 0856B4B31F72D2AC00905F3A /* MDRootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0856B4B21F72D2AC00905F3A /* MDRootViewController.m */; };
25 | /* End PBXBuildFile section */
26 |
27 | /* Begin PBXCopyFilesBuildPhase section */
28 | 08555F3B1F31773800591B10 /* Embed Frameworks */ = {
29 | isa = PBXCopyFilesBuildPhase;
30 | buildActionMask = 2147483647;
31 | dstPath = "";
32 | dstSubfolderSpec = 10;
33 | files = (
34 | 08555F411F31775600591B10 /* MDTransitioning_ImagePriview.framework in Embed Frameworks */,
35 | 08555F3E1F31775600591B10 /* MDTransitioning.framework in Embed Frameworks */,
36 | );
37 | name = "Embed Frameworks";
38 | runOnlyForDeploymentPostprocessing = 0;
39 | };
40 | /* End PBXCopyFilesBuildPhase section */
41 |
42 | /* Begin PBXFileReference section */
43 | 083D017C1F30577E00D1E530 /* Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Demo.app; sourceTree = BUILT_PRODUCTS_DIR; };
44 | 083D020B1F3057F400D1E530 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
45 | 083D020E1F3057F400D1E530 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = LaunchScreen.storyboard; sourceTree = ""; };
46 | 083D02101F3057F400D1E530 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Main.storyboard; sourceTree = ""; };
47 | 083D02111F3057F400D1E530 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
48 | 083D02121F3057F400D1E530 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
49 | 083D02131F3057F400D1E530 /* MDAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDAppDelegate.h; sourceTree = ""; };
50 | 083D02141F3057F400D1E530 /* MDAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDAppDelegate.m; sourceTree = ""; };
51 | 083D02151F3057F400D1E530 /* MDPresentedViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDPresentedViewController.h; sourceTree = ""; };
52 | 083D02161F3057F400D1E530 /* MDPresentedViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDPresentedViewController.m; sourceTree = ""; };
53 | 083D02171F3057F400D1E530 /* MDPresentionControlViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDPresentionControlViewController.h; sourceTree = ""; };
54 | 083D02181F3057F400D1E530 /* MDPresentionControlViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDPresentionControlViewController.m; sourceTree = ""; };
55 | 083D022F1F30626D00D1E530 /* MDCustomViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDCustomViewController.h; sourceTree = ""; };
56 | 083D02301F30626D00D1E530 /* MDCustomViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDCustomViewController.m; sourceTree = ""; };
57 | 08555F3C1F31775600591B10 /* MDTransitioning.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MDTransitioning.framework; sourceTree = BUILT_PRODUCTS_DIR; };
58 | 08555F3F1F31775600591B10 /* MDTransitioning_ImagePriview.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MDTransitioning_ImagePriview.framework; sourceTree = BUILT_PRODUCTS_DIR; };
59 | 0856B4A81F72CBDE00905F3A /* MDCustomImageViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDCustomImageViewController.h; sourceTree = ""; };
60 | 0856B4A91F72CBDE00905F3A /* MDCustomImageViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDCustomImageViewController.m; sourceTree = ""; };
61 | 0856B4AB1F72D06300905F3A /* MDVerticalSwipPopViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDVerticalSwipPopViewController.h; sourceTree = ""; };
62 | 0856B4AC1F72D06300905F3A /* MDVerticalSwipPopViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDVerticalSwipPopViewController.m; sourceTree = ""; };
63 | 0856B4B11F72D2AC00905F3A /* MDRootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDRootViewController.h; sourceTree = ""; };
64 | 0856B4B21F72D2AC00905F3A /* MDRootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDRootViewController.m; sourceTree = ""; };
65 | /* End PBXFileReference section */
66 |
67 | /* Begin PBXFrameworksBuildPhase section */
68 | 083D01791F30577E00D1E530 /* Frameworks */ = {
69 | isa = PBXFrameworksBuildPhase;
70 | buildActionMask = 2147483647;
71 | files = (
72 | 08555F401F31775600591B10 /* MDTransitioning_ImagePriview.framework in Frameworks */,
73 | 08555F3D1F31775600591B10 /* MDTransitioning.framework in Frameworks */,
74 | );
75 | runOnlyForDeploymentPostprocessing = 0;
76 | };
77 | /* End PBXFrameworksBuildPhase section */
78 |
79 | /* Begin PBXGroup section */
80 | 083D01731F30577E00D1E530 = {
81 | isa = PBXGroup;
82 | children = (
83 | 08555F3F1F31775600591B10 /* MDTransitioning_ImagePriview.framework */,
84 | 08555F3C1F31775600591B10 /* MDTransitioning.framework */,
85 | 083D020B1F3057F400D1E530 /* Assets.xcassets */,
86 | 083D020D1F3057F400D1E530 /* LaunchScreen.storyboard */,
87 | 083D020F1F3057F400D1E530 /* Main.storyboard */,
88 | 083D02111F3057F400D1E530 /* Info.plist */,
89 | 083D02121F3057F400D1E530 /* main.m */,
90 | 083D02131F3057F400D1E530 /* MDAppDelegate.h */,
91 | 083D02141F3057F400D1E530 /* MDAppDelegate.m */,
92 | 0856B4B11F72D2AC00905F3A /* MDRootViewController.h */,
93 | 0856B4B21F72D2AC00905F3A /* MDRootViewController.m */,
94 | 083D02171F3057F400D1E530 /* MDPresentionControlViewController.h */,
95 | 083D02181F3057F400D1E530 /* MDPresentionControlViewController.m */,
96 | 083D022F1F30626D00D1E530 /* MDCustomViewController.h */,
97 | 083D02301F30626D00D1E530 /* MDCustomViewController.m */,
98 | 0856B4A81F72CBDE00905F3A /* MDCustomImageViewController.h */,
99 | 0856B4A91F72CBDE00905F3A /* MDCustomImageViewController.m */,
100 | 0856B4AB1F72D06300905F3A /* MDVerticalSwipPopViewController.h */,
101 | 0856B4AC1F72D06300905F3A /* MDVerticalSwipPopViewController.m */,
102 | 083D02151F3057F400D1E530 /* MDPresentedViewController.h */,
103 | 083D02161F3057F400D1E530 /* MDPresentedViewController.m */,
104 | 083D017D1F30577E00D1E530 /* Products */,
105 | 083D02211F30585000D1E530 /* Frameworks */,
106 | );
107 | sourceTree = "";
108 | };
109 | 083D017D1F30577E00D1E530 /* Products */ = {
110 | isa = PBXGroup;
111 | children = (
112 | 083D017C1F30577E00D1E530 /* Demo.app */,
113 | );
114 | name = Products;
115 | sourceTree = "";
116 | };
117 | 083D02211F30585000D1E530 /* Frameworks */ = {
118 | isa = PBXGroup;
119 | children = (
120 | );
121 | name = Frameworks;
122 | sourceTree = "";
123 | };
124 | /* End PBXGroup section */
125 |
126 | /* Begin PBXNativeTarget section */
127 | 083D017B1F30577E00D1E530 /* Demo */ = {
128 | isa = PBXNativeTarget;
129 | buildConfigurationList = 083D01931F30577E00D1E530 /* Build configuration list for PBXNativeTarget "Demo" */;
130 | buildPhases = (
131 | 083D01781F30577E00D1E530 /* Sources */,
132 | 083D01791F30577E00D1E530 /* Frameworks */,
133 | 083D017A1F30577E00D1E530 /* Resources */,
134 | 08555F3B1F31773800591B10 /* Embed Frameworks */,
135 | );
136 | buildRules = (
137 | );
138 | dependencies = (
139 | );
140 | name = Demo;
141 | productName = Demo;
142 | productReference = 083D017C1F30577E00D1E530 /* Demo.app */;
143 | productType = "com.apple.product-type.application";
144 | };
145 | /* End PBXNativeTarget section */
146 |
147 | /* Begin PBXProject section */
148 | 083D01741F30577E00D1E530 /* Project object */ = {
149 | isa = PBXProject;
150 | attributes = {
151 | LastUpgradeCheck = 0930;
152 | ORGANIZATIONNAME = markejave;
153 | TargetAttributes = {
154 | 083D017B1F30577E00D1E530 = {
155 | CreatedOnToolsVersion = 8.3.3;
156 | DevelopmentTeam = 79E68V4GS2;
157 | ProvisioningStyle = Manual;
158 | };
159 | };
160 | };
161 | buildConfigurationList = 083D01771F30577E00D1E530 /* Build configuration list for PBXProject "Demo" */;
162 | compatibilityVersion = "Xcode 3.2";
163 | developmentRegion = English;
164 | hasScannedForEncodings = 0;
165 | knownRegions = (
166 | en,
167 | Base,
168 | );
169 | mainGroup = 083D01731F30577E00D1E530;
170 | productRefGroup = 083D017D1F30577E00D1E530 /* Products */;
171 | projectDirPath = "";
172 | projectRoot = "";
173 | targets = (
174 | 083D017B1F30577E00D1E530 /* Demo */,
175 | );
176 | };
177 | /* End PBXProject section */
178 |
179 | /* Begin PBXResourcesBuildPhase section */
180 | 083D017A1F30577E00D1E530 /* Resources */ = {
181 | isa = PBXResourcesBuildPhase;
182 | buildActionMask = 2147483647;
183 | files = (
184 | 083D021B1F3057F400D1E530 /* Main.storyboard in Resources */,
185 | 083D02191F3057F400D1E530 /* Assets.xcassets in Resources */,
186 | 083D021A1F3057F400D1E530 /* LaunchScreen.storyboard in Resources */,
187 | );
188 | runOnlyForDeploymentPostprocessing = 0;
189 | };
190 | /* End PBXResourcesBuildPhase section */
191 |
192 | /* Begin PBXSourcesBuildPhase section */
193 | 083D01781F30577E00D1E530 /* Sources */ = {
194 | isa = PBXSourcesBuildPhase;
195 | buildActionMask = 2147483647;
196 | files = (
197 | 0856B4AA1F72CBDE00905F3A /* MDCustomImageViewController.m in Sources */,
198 | 083D021D1F3057F400D1E530 /* main.m in Sources */,
199 | 083D02201F3057F400D1E530 /* MDPresentionControlViewController.m in Sources */,
200 | 083D021F1F3057F400D1E530 /* MDPresentedViewController.m in Sources */,
201 | 083D02311F30626D00D1E530 /* MDCustomViewController.m in Sources */,
202 | 0856B4B31F72D2AC00905F3A /* MDRootViewController.m in Sources */,
203 | 083D021E1F3057F400D1E530 /* MDAppDelegate.m in Sources */,
204 | 0856B4AD1F72D06300905F3A /* MDVerticalSwipPopViewController.m in Sources */,
205 | );
206 | runOnlyForDeploymentPostprocessing = 0;
207 | };
208 | /* End PBXSourcesBuildPhase section */
209 |
210 | /* Begin PBXVariantGroup section */
211 | 083D020D1F3057F400D1E530 /* LaunchScreen.storyboard */ = {
212 | isa = PBXVariantGroup;
213 | children = (
214 | 083D020E1F3057F400D1E530 /* Base */,
215 | );
216 | name = LaunchScreen.storyboard;
217 | path = Base.lproj;
218 | sourceTree = "";
219 | };
220 | 083D020F1F3057F400D1E530 /* Main.storyboard */ = {
221 | isa = PBXVariantGroup;
222 | children = (
223 | 083D02101F3057F400D1E530 /* Base */,
224 | );
225 | name = Main.storyboard;
226 | path = Base.lproj;
227 | sourceTree = "";
228 | };
229 | /* End PBXVariantGroup section */
230 |
231 | /* Begin XCBuildConfiguration section */
232 | 083D01911F30577E00D1E530 /* Debug */ = {
233 | isa = XCBuildConfiguration;
234 | buildSettings = {
235 | ALWAYS_SEARCH_USER_PATHS = NO;
236 | CLANG_ANALYZER_NONNULL = YES;
237 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
238 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
239 | CLANG_CXX_LIBRARY = "libc++";
240 | CLANG_ENABLE_MODULES = YES;
241 | CLANG_ENABLE_OBJC_ARC = YES;
242 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
243 | CLANG_WARN_BOOL_CONVERSION = YES;
244 | CLANG_WARN_COMMA = YES;
245 | CLANG_WARN_CONSTANT_CONVERSION = YES;
246 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
247 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
248 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
249 | CLANG_WARN_EMPTY_BODY = YES;
250 | CLANG_WARN_ENUM_CONVERSION = YES;
251 | CLANG_WARN_INFINITE_RECURSION = YES;
252 | CLANG_WARN_INT_CONVERSION = YES;
253 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
254 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
255 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
256 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
257 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
258 | CLANG_WARN_STRICT_PROTOTYPES = YES;
259 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
260 | CLANG_WARN_UNREACHABLE_CODE = YES;
261 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
262 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
263 | COPY_PHASE_STRIP = NO;
264 | DEBUG_INFORMATION_FORMAT = dwarf;
265 | ENABLE_STRICT_OBJC_MSGSEND = YES;
266 | ENABLE_TESTABILITY = YES;
267 | GCC_C_LANGUAGE_STANDARD = gnu99;
268 | GCC_DYNAMIC_NO_PIC = NO;
269 | GCC_NO_COMMON_BLOCKS = YES;
270 | GCC_OPTIMIZATION_LEVEL = 0;
271 | GCC_PREPROCESSOR_DEFINITIONS = (
272 | "DEBUG=1",
273 | "$(inherited)",
274 | );
275 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
276 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
277 | GCC_WARN_UNDECLARED_SELECTOR = YES;
278 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
279 | GCC_WARN_UNUSED_FUNCTION = YES;
280 | GCC_WARN_UNUSED_VARIABLE = YES;
281 | IPHONEOS_DEPLOYMENT_TARGET = 10.3;
282 | MTL_ENABLE_DEBUG_INFO = YES;
283 | ONLY_ACTIVE_ARCH = YES;
284 | SDKROOT = iphoneos;
285 | TARGETED_DEVICE_FAMILY = "1,2";
286 | };
287 | name = Debug;
288 | };
289 | 083D01921F30577E00D1E530 /* Release */ = {
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++0x";
296 | CLANG_CXX_LIBRARY = "libc++";
297 | CLANG_ENABLE_MODULES = YES;
298 | CLANG_ENABLE_OBJC_ARC = YES;
299 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
300 | CLANG_WARN_BOOL_CONVERSION = YES;
301 | CLANG_WARN_COMMA = YES;
302 | CLANG_WARN_CONSTANT_CONVERSION = YES;
303 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
304 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
305 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
306 | CLANG_WARN_EMPTY_BODY = YES;
307 | CLANG_WARN_ENUM_CONVERSION = YES;
308 | CLANG_WARN_INFINITE_RECURSION = YES;
309 | CLANG_WARN_INT_CONVERSION = YES;
310 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
311 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
312 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
313 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
314 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
315 | CLANG_WARN_STRICT_PROTOTYPES = YES;
316 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
317 | CLANG_WARN_UNREACHABLE_CODE = YES;
318 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
319 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
320 | COPY_PHASE_STRIP = NO;
321 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
322 | ENABLE_NS_ASSERTIONS = NO;
323 | ENABLE_STRICT_OBJC_MSGSEND = YES;
324 | GCC_C_LANGUAGE_STANDARD = gnu99;
325 | GCC_NO_COMMON_BLOCKS = YES;
326 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
327 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
328 | GCC_WARN_UNDECLARED_SELECTOR = YES;
329 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
330 | GCC_WARN_UNUSED_FUNCTION = YES;
331 | GCC_WARN_UNUSED_VARIABLE = YES;
332 | IPHONEOS_DEPLOYMENT_TARGET = 10.3;
333 | MTL_ENABLE_DEBUG_INFO = NO;
334 | SDKROOT = iphoneos;
335 | TARGETED_DEVICE_FAMILY = "1,2";
336 | VALIDATE_PRODUCT = YES;
337 | };
338 | name = Release;
339 | };
340 | 083D01941F30577E00D1E530 /* Debug */ = {
341 | isa = XCBuildConfiguration;
342 | buildSettings = {
343 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
344 | DEVELOPMENT_TEAM = 79E68V4GS2;
345 | INFOPLIST_FILE = Info.plist;
346 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
347 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
348 | PRODUCT_BUNDLE_IDENTIFIER = com.markejave.Demo;
349 | PRODUCT_NAME = "$(TARGET_NAME)";
350 | PROVISIONING_PROFILE = "c0d66c64-1571-4a6f-8b6c-afac376c527e";
351 | PROVISIONING_PROFILE_SPECIFIER = "all apps development profile";
352 | };
353 | name = Debug;
354 | };
355 | 083D01951F30577E00D1E530 /* Release */ = {
356 | isa = XCBuildConfiguration;
357 | buildSettings = {
358 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
359 | DEVELOPMENT_TEAM = 79E68V4GS2;
360 | INFOPLIST_FILE = Info.plist;
361 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
362 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
363 | PRODUCT_BUNDLE_IDENTIFIER = com.markejave.Demo;
364 | PRODUCT_NAME = "$(TARGET_NAME)";
365 | PROVISIONING_PROFILE = "c57274e6-e540-4463-b42f-6d513d4aaf58";
366 | PROVISIONING_PROFILE_SPECIFIER = "all apps development profile";
367 | };
368 | name = Release;
369 | };
370 | /* End XCBuildConfiguration section */
371 |
372 | /* Begin XCConfigurationList section */
373 | 083D01771F30577E00D1E530 /* Build configuration list for PBXProject "Demo" */ = {
374 | isa = XCConfigurationList;
375 | buildConfigurations = (
376 | 083D01911F30577E00D1E530 /* Debug */,
377 | 083D01921F30577E00D1E530 /* Release */,
378 | );
379 | defaultConfigurationIsVisible = 0;
380 | defaultConfigurationName = Release;
381 | };
382 | 083D01931F30577E00D1E530 /* Build configuration list for PBXNativeTarget "Demo" */ = {
383 | isa = XCConfigurationList;
384 | buildConfigurations = (
385 | 083D01941F30577E00D1E530 /* Debug */,
386 | 083D01951F30577E00D1E530 /* Release */,
387 | );
388 | defaultConfigurationIsVisible = 0;
389 | defaultConfigurationName = Release;
390 | };
391 | /* End XCConfigurationList section */
392 | };
393 | rootObject = 083D01741F30577E00D1E530 /* Project object */;
394 | }
395 |
--------------------------------------------------------------------------------
/Demo/Demo.xcodeproj/xcshareddata/xcschemes/Demo.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 |
--------------------------------------------------------------------------------
/Demo/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
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 |
--------------------------------------------------------------------------------
/Demo/MDAppDelegate.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import
22 |
23 | @interface MDAppDelegate : UIResponder
24 |
25 | @property (strong, nonatomic) UIWindow *window;
26 |
27 |
28 | @end
29 |
30 |
--------------------------------------------------------------------------------
/Demo/MDAppDelegate.m:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import "MDAppDelegate.h"
22 |
23 | @interface MDAppDelegate ()
24 |
25 | @end
26 |
27 | @implementation MDAppDelegate
28 |
29 |
30 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
31 | // Override point for customization after application launch.
32 |
33 | return YES;
34 | }
35 |
36 |
37 | - (void)applicationWillResignActive:(UIApplication *)application {
38 | // 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.
39 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
40 | }
41 |
42 |
43 | - (void)applicationDidEnterBackground:(UIApplication *)application {
44 | // 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.
45 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
46 | }
47 |
48 |
49 | - (void)applicationWillEnterForeground:(UIApplication *)application {
50 | // 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.
51 | }
52 |
53 |
54 | - (void)applicationDidBecomeActive:(UIApplication *)application {
55 | // 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.
56 | }
57 |
58 |
59 | - (void)applicationWillTerminate:(UIApplication *)application {
60 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
61 | }
62 |
63 |
64 | @end
65 |
--------------------------------------------------------------------------------
/Demo/MDCustomImageViewController.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import
22 |
23 | @interface MDCustomImageViewController : MDImageViewController
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/Demo/MDCustomImageViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // MDCustomImageViewController.m
3 | // Demo
4 | //
5 | // Created by 徐 林峰 on 2017/9/21.
6 | // Copyright © 2017年 markejave. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 | #import "MDCustomImageViewController.h"
12 |
13 | @interface MDCustomImageViewController ()
14 |
15 | @end
16 |
17 | @implementation MDCustomImageViewController
18 |
19 | - (id)initWithImage:(UIImage *)image;{
20 | if (self = [super initWithImage:image]) {
21 | self.modalPresentationStyle = UIModalPresentationFullScreen;
22 | }
23 | return self;
24 | }
25 |
26 | #pragma mark - MDPresentionController
27 |
28 | - (id)animationForPresentionOperation:(MDPresentionAnimatedOperation)operation fromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController;{
29 | if (operation == MDPresentionAnimatedOperationPresent) {
30 | MDImageZoomAnimationController *controller = [MDImageZoomAnimationController animationForPresentOperation:operation fromViewController:fromViewController toViewController:toViewController];
31 | controller.hideReferenceImageViewWhenZoomIn = NO;
32 | return controller;
33 | } else {
34 | return [[MDPresentionAnimationController alloc] initWithPresentionAnimatedOperation:operation fromViewController:fromViewController toViewController:toViewController];
35 | }
36 | }
37 |
38 | @end
39 |
--------------------------------------------------------------------------------
/Demo/MDCustomViewController.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import
22 |
23 | @interface MDCustomViewController : UIViewController
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/Demo/MDCustomViewController.m:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import "MDCustomViewController.h"
22 | #import
23 |
24 | @interface MDCustomViewController ()
25 |
26 | @end
27 |
28 | @implementation MDCustomViewController
29 |
30 | - (void)loadView{
31 | [super loadView];
32 |
33 | self.view.backgroundColor = [UIColor blueColor];
34 | }
35 |
36 | #pragma mark - MDNavigationPopController
37 |
38 | - (id)animationForNavigationOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController;{
39 | return [[MDScaleNavigationAnimationController alloc] initWithNavigationControllerOperation:operation fromViewController:fromViewController toViewController:toViewController];
40 | }
41 |
42 | @end
43 |
--------------------------------------------------------------------------------
/Demo/MDPresentedViewController.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import
22 |
23 | @interface MDPresentedViewController : UIViewController
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/Demo/MDPresentedViewController.m:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import
22 | #import "MDPresentedViewController.h"
23 |
24 | @interface MDPresentedViewController ()
25 |
26 | @end
27 |
28 | @implementation MDPresentedViewController
29 |
30 | - (void)viewDidLoad {
31 | [super viewDidLoad];
32 | // Do any additional setup after loading the view.
33 |
34 | self.view.backgroundColor = [UIColor redColor];
35 |
36 | UIButton *dismissButton = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
37 | [dismissButton setTitle:@"dismiss" forState:UIControlStateNormal];
38 | [dismissButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
39 |
40 | [dismissButton addTarget:self action:@selector(didClickDismiss:) forControlEvents:UIControlEventTouchUpInside];
41 |
42 | [[self view] addSubview:dismissButton];
43 |
44 | if ([self transitioningDelegate]) {
45 | MDVerticalSwipDismissInteractionController *interactionController = [MDVerticalSwipDismissInteractionController interactionControllerWithViewController:self];
46 | interactionController.verticalTranslation = CGRectGetHeight([[self view] bounds]);
47 |
48 | self.presentionInteractionController = interactionController;
49 | }
50 | }
51 |
52 | #pragma mark - actions
53 |
54 | - (IBAction)didClickDismiss:(id)sender{
55 | [self dismissViewControllerAnimated:YES completion:nil];
56 | }
57 |
58 | @end
59 |
--------------------------------------------------------------------------------
/Demo/MDPresentionControlViewController.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import
22 |
23 | @interface MDPresentionControlViewController : UIViewController
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/Demo/MDPresentionControlViewController.m:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import
22 | #import "MDPresentionControlViewController.h"
23 | #import "MDPresentedViewController.h"
24 | #import "MDCustomImageViewController.h"
25 |
26 | @interface MDPresentionControlViewController ()
27 |
28 | @property (weak, nonatomic) IBOutlet UIImageView *imageView;
29 |
30 | @end
31 |
32 | @implementation MDPresentionControlViewController
33 |
34 | - (void)loadView{
35 | [super loadView];
36 |
37 | self.view.backgroundColor = [UIColor brownColor];
38 | }
39 |
40 | #pragma mark - actions
41 |
42 | - (IBAction)didClickBackButton:(id)sender {
43 | [[self navigationController] popViewControllerAnimated:YES];
44 | }
45 |
46 | - (IBAction)didClickImageButton:(id)sender {
47 | MDImageViewController *imageViewController = [[MDImageViewController alloc] initWithImage:[[self imageView] image]];
48 | imageViewController.transitioningDelegate = [MDPresentionControllerDelegate delegateWithReferenceViewController:self];
49 |
50 | [self presentViewController:imageViewController animated:YES completion:nil];
51 | }
52 |
53 | - (IBAction)didClickSystemPresent:(id)sender {
54 | MDPresentedViewController *presentViewController = [MDPresentedViewController new];
55 | [self presentViewController:presentViewController animated:YES completion:nil];
56 | }
57 |
58 | - (IBAction)didClickPresent:(id)sender {
59 | MDPresentedViewController *presentViewController = [MDPresentedViewController new];
60 | presentViewController.transitioningDelegate = [MDPresentionControllerDelegate delegateWithReferenceViewController:self];
61 |
62 | [self presentViewController:presentViewController animated:YES completion:nil];
63 | }
64 |
65 | @end
66 |
--------------------------------------------------------------------------------
/Demo/MDRootViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // MDRootViewController.h
3 | // Demo
4 | //
5 | // Created by 徐 林峰 on 2017/9/21.
6 | // Copyright © 2017年 markejave. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface MDRootViewController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/Demo/MDRootViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // MDRootViewController.m
3 | // Demo
4 | //
5 | // Created by 徐 林峰 on 2017/9/21.
6 | // Copyright © 2017年 markejave. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "MDRootViewController.h"
11 | #import "MDCustomViewController.h"
12 | #import "MDPresentionControlViewController.h"
13 | #import "MDVerticalSwipPopViewController.h"
14 |
15 | @interface MDRootViewController ()
16 |
17 | @property (nonatomic, strong) UIColor *backgroundColor;
18 |
19 | @end
20 |
21 | @implementation MDRootViewController
22 |
23 | - (void)viewDidLoad{
24 | [super viewDidLoad];
25 |
26 | if ([self backgroundColor]) self.view.backgroundColor = [UIColor brownColor];
27 |
28 | self.navigationController.navigationBarHidden = YES;
29 | }
30 |
31 | - (void)didReceiveMemoryWarning {
32 | [super didReceiveMemoryWarning];
33 | // Dispose of any resources that can be recreated.
34 | }
35 |
36 | - (IBAction)didClickSystemPush:(id)sender {
37 | MDPresentionControlViewController * viewController = [[UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:@"MDPresentionControlViewController"];
38 | viewController.allowPopInteractive = NO;
39 | viewController.hidesBottomBarWhenPushed = YES;
40 |
41 | self.navigationController.delegate = nil;
42 | [[self navigationController] pushViewController:viewController animated:YES];
43 | }
44 |
45 | - (IBAction)didClickNormalPush:(id)sender {
46 | MDRootViewController *viewController = [MDRootViewController new];
47 | viewController.backgroundColor = [UIColor brownColor];
48 | viewController.hidesBottomBarWhenPushed = YES;
49 |
50 | self.navigationController.allowPushAnimation = YES;
51 | self.navigationController.delegate = [MDNavigationControllerDelegate defaultDelegate];
52 |
53 | [[self navigationController] pushViewController:viewController animated:YES];
54 | }
55 |
56 | - (IBAction)didClickScalePush:(id)sender {
57 | MDCustomViewController *viewController = [MDCustomViewController new];
58 | viewController.hidesBottomBarWhenPushed = YES;
59 |
60 | self.navigationController.allowPushAnimation = YES;
61 | self.navigationController.delegate = [MDNavigationControllerDelegate defaultDelegate];
62 |
63 | [[self navigationController] pushViewController:viewController animated:YES];
64 | }
65 |
66 | - (IBAction)didClickVerticalPush:(id)sender {
67 | MDVerticalSwipPopViewController *viewController = [MDVerticalSwipPopViewController new];
68 | viewController.hidesBottomBarWhenPushed = YES;
69 |
70 | self.navigationController.allowPushAnimation = YES;
71 | self.navigationController.delegate = [MDNavigationControllerDelegate defaultDelegate];
72 |
73 | [[self navigationController] pushViewController:viewController animated:YES];
74 | }
75 |
76 | @end
77 |
--------------------------------------------------------------------------------
/Demo/MDVerticalSwipPopViewController.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import
22 |
23 | @interface MDVerticalSwipPopViewController : UIViewController
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/Demo/MDVerticalSwipPopViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // MDVerticalSwipPopViewController.m
3 | // Demo
4 | //
5 | // Created by 徐 林峰 on 2017/9/21.
6 | // Copyright © 2017年 markejave. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "MDVerticalSwipPopViewController.h"
11 |
12 | @interface MDVerticalSwipPopViewController ()
13 |
14 | @end
15 |
16 | @implementation MDVerticalSwipPopViewController
17 |
18 | - (void)loadView{
19 | [super loadView];
20 |
21 | self.view.backgroundColor = [UIColor greenColor];
22 | }
23 |
24 | - (id)requirePopInteractionController{
25 | return [MDVerticalSwipPopInteractionController interactionControllerWithViewController:self];
26 | }
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/Demo/main.m:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import
22 | #import "MDAppDelegate.h"
23 |
24 | int main(int argc, char * argv[]) {
25 | @autoreleasepool {
26 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([MDAppDelegate class]));
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/ImagePreview/MDImageDismissInteractionController.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import
22 |
23 | @interface MDImageDismissInteractionController : MDSwipeInteractionController
24 |
25 | // The max distance of translation, default is controller.view.width / 3.f.
26 | @property (nonatomic, assign) CGFloat translation;
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/ImagePreview/MDImageDismissInteractionController.m:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import "MDImageDismissInteractionController.h"
22 | #import "MDImageZoomAnimationController.h"
23 |
24 | @implementation MDImageDismissInteractionController
25 |
26 | - (instancetype)initWithViewController:(UIViewController *)viewController{
27 | if (self = [super initWithViewController:viewController]) {
28 | NSParameterAssert([viewController conformsToProtocol:@protocol(MDImageContainerViewControllerDelegate)]);
29 |
30 | __block __weak id weak_self = self;
31 | self.translation = CGRectGetWidth([[viewController view] bounds]) / 3.;
32 | self.begin = ^(id interactiveTransition){
33 | [viewController dismissViewControllerAnimated:YES completion:nil];
34 | };
35 | self.allowSwipe = ^CGFloat(CGPoint location, CGPoint velocity) {
36 | return [[viewController scrollView] zoomScale] <= [[viewController scrollView] minimumZoomScale] && velocity.y > 0;
37 | };
38 | self.progress = ^CGFloat(CGPoint location, CGPoint translation, CGPoint velocity) {
39 | CGFloat distance = sqrt(pow(translation.x, 2) + pow(translation.y, 2));
40 | return distance / [weak_self translation];
41 | };
42 | }
43 | return self;
44 | }
45 |
46 | @end
47 |
--------------------------------------------------------------------------------
/ImagePreview/MDImageDraggingDismissInteractionController.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import
22 |
23 | @interface MDImageDraggingDismissInteractionController : MDSwipeInteractionController
24 |
25 | // The max distance of dragging translation, default is controller.view.width / 3.f.
26 | @property (nonatomic, assign) CGFloat translation;
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/ImagePreview/MDImageDraggingDismissInteractionController.m:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import "MDImageDraggingDismissInteractionController.h"
22 | #import "MDImageZoomAnimationController.h"
23 |
24 | @interface MDImageDraggingDismissInteractionController ()
25 |
26 | @property (nonatomic, weak, readonly) UIViewController *viewController;
27 |
28 | @property (nonatomic, strong, readonly) UIPanGestureRecognizer *panGestureRecognizer;
29 |
30 | @property (nonatomic, assign) BOOL interactionInProgress;
31 |
32 | @end
33 |
34 | @implementation MDImageDraggingDismissInteractionController
35 | @dynamic interactiveTransition, interactionInProgress, viewController, panGestureRecognizer;
36 |
37 | - (instancetype)initWithViewController:(UIViewController *)viewController{
38 | if (self = [super initWithViewController:viewController]) {
39 | NSParameterAssert([viewController conformsToProtocol:@protocol(MDImageContainerViewControllerDelegate)]);
40 | self.translation = CGRectGetWidth([[viewController view] bounds]) / 3.;
41 | }
42 | return self;
43 | }
44 |
45 | #pragma mark - UIPanGestureRecognizer handlers
46 |
47 | - (void)handlePanGestureRecognizer:(UIPanGestureRecognizer *)recognizer {
48 | CGPoint translation = [recognizer translationInView:[[self viewController] view]];
49 |
50 | if ([recognizer state] == UIGestureRecognizerStateBegan) {
51 | self.interactionInProgress = YES;
52 | } else if ([recognizer state] == UIGestureRecognizerStateChanged) {
53 | CGFloat progress = sqrt(pow(translation.x, 2) + pow(translation.y, 2)) / [self translation];
54 | progress = MIN(1.0, MAX(0.0, progress));
55 | self.viewController.imageView.transform = CGAffineTransformIdentity;
56 | self.viewController.imageView.transform = CGAffineTransformScale(CGAffineTransformTranslate(CGAffineTransformIdentity, translation.x, translation.y), 1 - progress / 2., 1 - progress / 2.);
57 | self.viewController.backgroundView.alpha = (1 - progress);
58 | } else if ([recognizer state] == UIGestureRecognizerStateEnded || [recognizer state] == UIGestureRecognizerStateCancelled) {
59 | CGFloat progress = sqrt(pow(translation.x, 2) + pow(translation.y, 2)) / [self translation];
60 | progress = MIN(1.0, MAX(0.0, progress));
61 | // Finish or cancel the interactive transition
62 | if (progress > 0.5) {
63 | [[self viewController] dismissViewControllerAnimated:YES completion:nil];
64 | } else {
65 | [UIView animateWithDuration:0.2 animations:^{
66 | self.viewController.backgroundView.alpha = 1.f;
67 | self.viewController.imageView.transform = CGAffineTransformIdentity;
68 | }];
69 | }
70 | self.interactionInProgress = NO;
71 | }
72 | }
73 |
74 | #pragma mark - UIGestureRecognizerDelegate
75 |
76 | - (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)recognizer {
77 | UIScrollView *scrollView = [[self viewController] scrollView];
78 |
79 | return recognizer == [self panGestureRecognizer] && [scrollView zoomScale] <= [scrollView minimumZoomScale];
80 | }
81 |
82 | @end
83 |
--------------------------------------------------------------------------------
/ImagePreview/MDImageViewController.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import "MDImageZoomAnimationController.h"
22 |
23 | // Simple full screen image viewer.
24 | //
25 | // Allows the user to view an image in full screen and double tap to zoom it.
26 | // The view controller can be dismissed with a single tap.
27 | @interface MDImageViewController : UIViewController
28 |
29 | // The background view.
30 | @property (nonatomic, strong, readonly) IBOutlet UIView *backgroundView;
31 |
32 | // The scroll view used for zooming.
33 | @property (nonatomic, strong, readonly) IBOutlet UIScrollView *scrollView;
34 |
35 | // The image view that displays the image.
36 | @property (nonatomic, strong, readonly) IBOutlet UIImageView *imageView;
37 |
38 | // The image that will be shown.
39 | @property (nonatomic, strong, readonly) UIImage *image;
40 |
41 | // The imageURL that will be downloaded and shown.
42 | @property (nonatomic, copy, readonly) NSURL *imageURL;
43 |
44 | // Initializes the receiver with the specified image.
45 | - (instancetype)initWithImage:(UIImage *)image;
46 |
47 | // Initializes the receiver with the specified image URL and placeholder.
48 | - (instancetype)initWithImageURL:(NSURL *)imageURL placeholderImage:(UIImage *)placeholderImage;
49 |
50 | @end
51 |
--------------------------------------------------------------------------------
/ImagePreview/MDImageViewController.m:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import
22 | #import "MDImageViewController.h"
23 | #import "MDImageDismissInteractionController.h"
24 | #import "MDImageDraggingDismissInteractionController.h"
25 |
26 | @interface MDImageViewController ()
27 |
28 | @property (nonatomic, strong) IBOutlet UIView *backgroundView;
29 |
30 | @property (nonatomic, strong) IBOutlet UIScrollView *scrollView;
31 |
32 | @property (nonatomic, strong) IBOutlet UIImageView *imageView;
33 |
34 | @property (nonatomic, strong) IBOutlet UITapGestureRecognizer *singleTapGestureRecognizer;
35 |
36 | @property (nonatomic, strong) IBOutlet UITapGestureRecognizer *doubleTapGestureRecognizer;
37 |
38 | @property (nonatomic, strong) UIImage *image;
39 |
40 | @property (nonatomic, copy) NSURL *imageURL;
41 |
42 | @end
43 |
44 | @implementation MDImageViewController
45 |
46 | - (instancetype)initWithImage:(UIImage *)image;{
47 | return [self initWithImageURL:nil placeholderImage:image];
48 | }
49 |
50 | - (instancetype)initWithImageURL:(NSURL *)imageURL placeholderImage:(UIImage *)placeholderImage;{
51 | if (self = [super init]) {
52 | self.imageURL = imageURL;
53 | self.image = placeholderImage;
54 | self.modalPresentationStyle = UIModalPresentationCustom;
55 | }
56 | return self;
57 | }
58 |
59 | - (void)loadView{
60 | [super loadView];
61 |
62 | self.view.backgroundColor = [UIColor clearColor];
63 | self.scrollView.contentSize = self.view.bounds.size;
64 |
65 | [[self view] addSubview:[self backgroundView]];
66 | [[self view] addSubview:[self scrollView]];
67 | [[self scrollView] addSubview:[self imageView]];
68 |
69 | [[self imageView] addGestureRecognizer:[self singleTapGestureRecognizer]];
70 | [[self imageView] addGestureRecognizer:[self doubleTapGestureRecognizer]];
71 | }
72 |
73 | - (void)viewDidLoad {
74 | [super viewDidLoad];
75 |
76 | // self.presentionInteractionController = [MDImageDismissInteractionController interactionControllerWithViewController:self];
77 | MDImageDraggingDismissInteractionController *interactionController = [MDImageDraggingDismissInteractionController interactionControllerWithViewController:self];
78 | interactionController.translation = 200.f;
79 |
80 | self.presentionInteractionController = interactionController;
81 |
82 | [[self singleTapGestureRecognizer] requireGestureRecognizerToFail:[self doubleTapGestureRecognizer]];
83 | }
84 |
85 | #pragma mark - accessor
86 |
87 | - (UIView *)backgroundView{
88 | if (!_backgroundView) {
89 | _backgroundView = [[UIView alloc] initWithFrame:[[self view] bounds]];
90 | _backgroundView.backgroundColor = [UIColor blackColor];
91 | }
92 | return _backgroundView;
93 | }
94 |
95 | - (UIScrollView *)scrollView{
96 | if (!_scrollView) {
97 | _scrollView = [[UIScrollView alloc] initWithFrame:[[self view] bounds]];
98 | _scrollView.delegate = self;
99 | _scrollView.maximumZoomScale = 2;
100 | }
101 | return _scrollView;
102 | }
103 |
104 | - (UIImageView *)imageView{
105 | if (!_imageView) {
106 | _imageView = [[UIImageView alloc] initWithFrame:[[self view] bounds]];
107 | _imageView.image = [self image];
108 | _imageView.userInteractionEnabled = YES;
109 | _imageView.multipleTouchEnabled = YES;
110 | _imageView.contentMode = UIViewContentModeScaleAspectFit;
111 |
112 | if ([self imageURL]) {
113 | _imageView.image = [UIImage imageWithContentsOfFile:[[self imageURL] absoluteString]];
114 | }
115 | }
116 | return _imageView;
117 | }
118 |
119 | - (UITapGestureRecognizer *)singleTapGestureRecognizer{
120 | if (!_singleTapGestureRecognizer) {
121 | _singleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
122 | _singleTapGestureRecognizer.numberOfTapsRequired = 1;
123 | }
124 | return _singleTapGestureRecognizer;
125 | }
126 |
127 | - (UITapGestureRecognizer *)doubleTapGestureRecognizer{
128 | if (!_doubleTapGestureRecognizer) {
129 | _doubleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)];
130 | _doubleTapGestureRecognizer.numberOfTapsRequired = 2;
131 | }
132 | return _doubleTapGestureRecognizer;
133 | }
134 |
135 | #pragma mark - UIScrollViewDelegate
136 |
137 | - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
138 | return [self imageView];
139 | }
140 |
141 | #pragma mark - MDPresentionController
142 |
143 | - (id)animationForPresentionOperation:(MDPresentionAnimatedOperation)operation fromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController;{
144 | return [MDImageZoomAnimationController animationForPresentOperation:operation fromViewController:fromViewController toViewController:toViewController];
145 | }
146 |
147 | #pragma mark - actions
148 |
149 | - (IBAction)handleSingleTap:(UITapGestureRecognizer *)tapGestureRecognizer {
150 | [self dismissViewControllerAnimated:YES completion:nil];
151 | }
152 |
153 | - (IBAction)handleDoubleTap:(UITapGestureRecognizer *)tapGestureRecognizer {
154 | if ([[self scrollView] zoomScale] == [[self scrollView] minimumZoomScale]) {
155 | // Zoom in
156 | CGPoint center = [tapGestureRecognizer locationInView:[self scrollView]];
157 | CGSize size = CGSizeMake(self.scrollView.bounds.size.width / self.scrollView.maximumZoomScale,
158 | self.scrollView.bounds.size.height / self.scrollView.maximumZoomScale);
159 | CGRect rect = CGRectMake(center.x - (size.width / 2.0), center.y - (size.height / 2.0), size.width, size.height);
160 | [[self scrollView] zoomToRect:rect animated:YES];
161 | } else {
162 | // Zoom out
163 | [[self scrollView] zoomToRect:[[self scrollView] bounds] animated:YES];
164 | }
165 | }
166 |
167 | @end
168 |
--------------------------------------------------------------------------------
/ImagePreview/MDImageZoomAnimationController.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import
22 |
23 | // Image zoom custom transition.
24 | @interface MDImageZoomAnimationController : NSObject
25 |
26 | // The image view that will be used as the source (zoom in) or destination
27 | // (zoom out) of the transition.
28 | @property (nonatomic, weak, readonly) UIImageView *referenceImageView;
29 |
30 | @property (nonatomic, assign) BOOL hideReferenceImageViewWhenZoomIn; // Default is YES.
31 |
32 | // Initializes the receiver with the specified reference image view to other image view.
33 | - (instancetype)initWithReferenceImageView:(UIImageView *)referenceImageView;
34 |
35 | @end
36 |
37 | // Support MPresentionAnimatedTransitioning
38 | @protocol MDImageZoomViewControllerDelegate
39 |
40 | @property (nonatomic, weak, readonly) UIImageView *imageView;
41 |
42 | @end
43 |
44 | @protocol MDImageContainerViewControllerDelegate
45 |
46 | @property (nonatomic, weak, readonly) UIView *backgroundView;
47 | @property (nonatomic, weak, readonly) UIScrollView *scrollView;
48 |
49 | @end
50 |
51 | @interface MDImageZoomAnimationController (MPresentionAnimatedTransitioning)
52 |
53 | + (id)animationForPresentOperation:(MDPresentionAnimatedOperation)presentionAnimatedOperation fromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController;
54 |
55 | - (instancetype)initWithPresentionAnimatedOperation:(MDPresentionAnimatedOperation)presentionAnimatedOperation fromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController;
56 |
57 | @end
58 |
--------------------------------------------------------------------------------
/ImagePreview/MDImageZoomAnimationController.m:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import "MDImageZoomAnimationController.h"
22 |
23 | CGRect MDImageZoomAnimationControllerAspectFitRectForSize(UIImage *image, CGSize size){
24 | CGFloat targetAspect = size.width / size.height;
25 | CGFloat sourceAspect = image.size.width / image.size.height;
26 | CGRect rect = CGRectZero;
27 |
28 | if (targetAspect > sourceAspect) {
29 | rect.size.height = size.height;
30 | rect.size.width = ceilf(rect.size.height * sourceAspect);
31 | rect.origin.x = ceilf((size.width - rect.size.width) * 0.5);
32 | }
33 | else {
34 | rect.size.width = size.width;
35 | rect.size.height = ceilf(rect.size.width / sourceAspect);
36 | rect.origin.y = ceilf((size.height - rect.size.height) * 0.5);
37 | }
38 |
39 | return rect;
40 | }
41 |
42 | @interface MDImageZoomAnimationController ()
43 |
44 | @property (nonatomic, assign) NSTimeInterval duration;
45 |
46 | @property (nonatomic, assign) MDPresentionAnimatedOperation presentionAnimatedOperation;
47 |
48 | @property (nonatomic, weak) UIViewController *fromViewController;
49 | @property (nonatomic, weak) UIViewController *toViewController;
50 |
51 | @end
52 |
53 | @implementation MDImageZoomAnimationController
54 |
55 | - (instancetype)initWithReferenceImageView:(UIImageView *)referenceImageView;{
56 | if (self = [super init]) {
57 | NSAssert([referenceImageView contentMode] == UIViewContentModeScaleAspectFill, @"*** referenceImageView must have a UIViewContentModeScaleAspectFill contentMode!");
58 | _referenceImageView = referenceImageView;
59 | _hideReferenceImageViewWhenZoomIn = YES;
60 | }
61 | return self;
62 | }
63 |
64 | - (NSTimeInterval)transitionDuration:(id)transitioning {
65 | UIViewController *viewController = [transitioning viewControllerForKey:UITransitionContextToViewControllerKey];
66 | return [viewController isBeingPresented] ? 0.5 : 0.25;
67 | }
68 |
69 | - (void)animateTransition:(id)transitioning {
70 | if ([self presentionAnimatedOperation] == MDPresentionAnimatedOperationPresent) {
71 | [self zoomInTransitioning:transitioning];
72 | } else if ([self presentionAnimatedOperation] == MDPresentionAnimatedOperationDismiss) {
73 | [self zoomOutTransitioning:transitioning];
74 | }
75 | }
76 |
77 | - (void)zoomInTransitioning:(id)transitioning {
78 | // Get the view controllers participating in the transition
79 | UIViewController *fromViewController = [transitioning viewControllerForKey:UITransitionContextFromViewControllerKey];
80 | UIViewController *toViewController = (id)[transitioning viewControllerForKey:UITransitionContextToViewControllerKey];
81 | NSAssert([toViewController conformsToProtocol:@protocol(MDImageZoomViewControllerDelegate)], @"*** toViewController must conforms to protocol for YRImageViewController!");
82 |
83 | UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
84 |
85 | UIView *containerView = [transitioning containerView];
86 | UIColor *windowBackgroundColor = [window backgroundColor];
87 |
88 | window.backgroundColor = [UIColor blackColor];
89 | // Create a temporary view for the zoom in transition and set the initial frame based
90 | // on the reference image view
91 | UIImageView *imageView = [[UIImageView alloc] initWithImage:[[self referenceImageView] image]];
92 | imageView.contentMode = UIViewContentModeScaleAspectFill;
93 | imageView.clipsToBounds = YES;
94 | imageView.frame = [containerView convertRect:[[self referenceImageView] bounds] fromView:[self referenceImageView]];
95 | [containerView addSubview:imageView];
96 | [containerView sendSubviewToBack:[fromViewController view]];
97 |
98 | // Compute the final frame for the temporary view
99 | CGRect finalFrame = [transitioning finalFrameForViewController:toViewController];
100 | CGRect transitionViewFinalFrame = MDImageZoomAnimationControllerAspectFitRectForSize([[self referenceImageView] image], finalFrame.size);
101 |
102 | if ([self hideReferenceImageViewWhenZoomIn]) {
103 | self.referenceImageView.hidden = YES;
104 | }
105 | // Perform the transition using a spring motion effect
106 | NSTimeInterval duration = [self transitionDuration:transitioning];
107 |
108 | [UIView animateWithDuration:duration
109 | delay:0
110 | usingSpringWithDamping:0.7
111 | initialSpringVelocity:0
112 | options:UIViewAnimationOptionCurveLinear
113 | animations:^{
114 | fromViewController.view.alpha = 0;
115 | imageView.frame = transitionViewFinalFrame;
116 | }
117 | completion:^(BOOL finished) {
118 | window.backgroundColor = windowBackgroundColor;
119 | fromViewController.view.alpha = 1;
120 |
121 | if ([transitioning transitionWasCancelled] && [self hideReferenceImageViewWhenZoomIn]) {
122 | self.referenceImageView.hidden = NO;
123 | }
124 |
125 | [imageView removeFromSuperview];
126 |
127 | if (![transitioning transitionWasCancelled]) {
128 | [containerView addSubview:[toViewController view]];
129 | }
130 |
131 | [transitioning completeTransition:![transitioning transitionWasCancelled]];
132 | }];
133 | }
134 |
135 | - (void)zoomOutTransitioning:(id)transitioning {
136 | // Get the view controllers participating in the transition
137 | UIViewController *toViewController = [transitioning viewControllerForKey:UITransitionContextToViewControllerKey];
138 | UIViewController *fromViewController = (id)[transitioning viewControllerForKey:UITransitionContextFromViewControllerKey];
139 | NSAssert([fromViewController conformsToProtocol:@protocol(MDImageZoomViewControllerDelegate)], @"*** fromViewController must conforms to protocol for YRImageViewController!");
140 | UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
141 |
142 | UIView *containerView = [transitioning containerView];
143 | UIColor *windowBackgroundColor = [window backgroundColor];
144 |
145 | // The toViewController view will fade in during the transition
146 | toViewController.view.frame = [transitioning finalFrameForViewController:toViewController];
147 |
148 | if ([fromViewController modalPresentationStyle] == UIModalPresentationNone) {
149 | toViewController.view.alpha = 0;
150 | window.backgroundColor = [UIColor blackColor];
151 |
152 | [containerView addSubview:[toViewController view]];
153 | [containerView sendSubviewToBack:[toViewController view]];
154 | }
155 | // Compute the initial frame for the temporary view based on the image view
156 | // of the YRImageViewController
157 | UIImageView *referenceImageView = [self referenceImageView];
158 | UIImageView *fromReferenceImageView = [fromViewController imageView];
159 | CGRect transitionViewInitialFrame = MDImageZoomAnimationControllerAspectFitRectForSize([fromReferenceImageView image], [fromReferenceImageView bounds].size);
160 | transitionViewInitialFrame = [containerView convertRect:transitionViewInitialFrame fromView:fromReferenceImageView];
161 |
162 | // Compute the final frame for the temporary view based on the reference
163 | // image view
164 | CGRect transitionViewFinalFrame = [containerView convertRect:[referenceImageView bounds] fromView:referenceImageView];
165 |
166 | // Create a temporary view for the zoom out transition based on the image
167 | // view controller contents
168 | UIImageView *imageView = [[UIImageView alloc] initWithImage:[fromReferenceImageView image]];
169 | imageView.contentMode = UIViewContentModeScaleAspectFill;
170 | imageView.layer.cornerRadius = [[referenceImageView layer] cornerRadius];
171 | imageView.layer.borderWidth = [[referenceImageView layer] borderWidth];
172 | imageView.layer.borderColor = [[referenceImageView layer] borderColor];
173 | imageView.clipsToBounds = YES;
174 | imageView.frame = transitionViewInitialFrame;
175 |
176 | [containerView addSubview:imageView];
177 |
178 | fromReferenceImageView.hidden = YES;
179 | if ([self hideReferenceImageViewWhenZoomIn]) {
180 | referenceImageView.hidden = YES;
181 | }
182 | // Perform the transition
183 | NSTimeInterval duration = [self transitionDuration:transitioning];
184 |
185 | [UIView animateWithDuration:duration
186 | delay:0
187 | options:UIViewAnimationOptionCurveEaseInOut
188 | animations:^{
189 | toViewController.view.alpha = 1.f;
190 | fromViewController.view.alpha = 0.f;
191 | imageView.frame = transitionViewFinalFrame;
192 | } completion:^(BOOL finished) {
193 | if ([self hideReferenceImageViewWhenZoomIn]) {
194 | referenceImageView.hidden = NO;
195 | }
196 | window.backgroundColor = windowBackgroundColor;
197 | [imageView removeFromSuperview];
198 |
199 | if ([transitioning transitionWasCancelled]) {
200 | fromReferenceImageView.hidden = NO;
201 | fromViewController.view.alpha = 1.f;
202 | [[toViewController view] removeFromSuperview];
203 | }
204 | [transitioning completeTransition:![transitioning transitionWasCancelled]];
205 | }];
206 | }
207 |
208 | @end
209 |
210 | @implementation MDImageZoomAnimationController (MPresentionAnimatedTransitioning)
211 |
212 | + (id)animationForPresentOperation:(MDPresentionAnimatedOperation)presentionAnimatedOperation fromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController;{
213 | return [[self alloc] initWithPresentionAnimatedOperation:presentionAnimatedOperation fromViewController:fromViewController toViewController:toViewController];
214 | }
215 |
216 | - (instancetype)initWithPresentionAnimatedOperation:(MDPresentionAnimatedOperation)presentionAnimatedOperation fromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController;{
217 |
218 | NSParameterAssert(presentionAnimatedOperation != MDPresentionAnimatedOperationNone);
219 | NSParameterAssert([fromViewController respondsToSelector:@selector(imageView)]);
220 | NSParameterAssert([toViewController respondsToSelector:@selector(imageView)]);
221 |
222 | UIImageView *referenceImageView = presentionAnimatedOperation == MDPresentionAnimatedOperationPresent ? [fromViewController imageView] : [toViewController imageView];
223 | if (self = [self initWithReferenceImageView:referenceImageView]) {
224 | self.presentionAnimatedOperation = presentionAnimatedOperation;
225 | self.fromViewController = fromViewController;
226 | self.toViewController = toViewController;
227 | self.hideReferenceImageViewWhenZoomIn = YES;
228 | }
229 | return self;
230 | }
231 |
232 | @end
233 |
--------------------------------------------------------------------------------
/ImagePreview/MDTransitioning+ImagePreview.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | //! Project version number for MDTransitioning.
22 | FOUNDATION_EXPORT double MDTransitioning_ImagePreviewVersionNumber;
23 |
24 | //! Project version string for MDTransitioning.
25 | FOUNDATION_EXPORT const unsigned char MDTransitioning_ImagePreviewVersionString[];
26 |
27 | // In this header, you should import all the public headers of your framework using statements like #import
28 |
29 | #import
30 | #import
31 | #import
32 | #import
33 |
--------------------------------------------------------------------------------
/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSPrincipalClass
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Modool
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/MDTransitioning.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## MDTransitioning
4 | @copyright Modool
5 |
6 | ### 前言
7 |
8 | 转场动画就是以某种方式从一个场景以动画的形式过渡到另一个场景。
9 |
10 | 然而,动画的可变性太强,每个设计师都有自己的想法,对于开发来说,是无法用固定的模式来限制动画的实现。
11 | 其次,系统已经为我们提供了一套很好的动画模板,我们只需要实现其相关方法,就能够很容易的实现各种各样的动画。
12 |
13 | 所以,本文将要介绍的并不是转场所需要的动画,而是针对"转场过程控制"的一种设计方案,以便提供一种具有可定制,可扩展的设计方案。
14 |
15 | 为了方便集成,我们也提供了很多套可选的动画方案,比如传统的侧滑、缩放、图片预览等等。
16 |
17 | ###iOS7 以前
18 |
19 | 在 iOS7 以前,系统不支持手势右划返回的,只能实现一些过度动画,如以下方案:
20 |
21 | ```
22 | // Code here
23 | // Custom present
24 | [toViewController willMoveToParentViewController:self];
25 | [fromViewController willMoveToParentViewController:nil];
26 |
27 | [self addChildViewController:toViewController];
28 | [[self view] addSubview:[toViewController view]];
29 |
30 | [self transitionFromViewController:fromViewController
31 | toViewController:toViewController
32 | duration:0.3
33 | options:UIViewAnimationOptionTransitionCrossDissolve
34 | animations:^{
35 | // 过度效果
36 | }
37 | completion:^(BOOL finished) {
38 | [fromViewController removeFromSuperView];
39 | [fromViewController removeFromParentViewController];
40 | [fromViewController didMoveToParentViewController:nil];
41 | [toViewController didMoveToParentViewController:self];
42 | }];
43 | ```
44 | 或者
45 |
46 | ```
47 | // Code here
48 | [navigationController pushViewController:toViewController animated:NO];
49 | [UIView animateWithDuration:0.3
50 | options:UIViewAnimationOptionTransitionCrossDissolve
51 | animations:^{
52 | // 过度效果
53 | }
54 | completion:nil];
55 | ```
56 | iOS7以前,没有为`Controller` 提供 `transitioningDelegate`
57 |
58 | ```
59 | // Code here
60 | @interface UIViewController(UIViewControllerTransitioning)
61 |
62 | @property (nullable, nonatomic, weak) id transitioningDelegate;
63 |
64 | @end
65 |
66 | ```
67 | 所以对于`Present`、`Dismiss`来说,尚且还是可以实现,而对于`Push` 和 `Pop`的定制非常困难,就更不要说针对转场来进行交互控制。
68 |
69 | ###iOS7 以后
70 |
71 | 在 iOS7 以后,系统针对交互转场这方面出现了很大变化,不仅支持了手势交互,还提供了一套标准的转场协议和动画协议。
72 |
73 | ####默认交互方案
74 |
75 | 首先,我们来看下 `Push` 和 `Pop`,在我们不去实现任何交互,以及任何动画的时候,系统所提供给我们的交互方案:
76 |
77 | ```
78 | // Code here
79 | @interface UINavigationController : UIViewController
80 |
81 | // 系统默认提供的侧滑手势(从屏幕边界往右划)
82 | @property(nullable, nonatomic, readonly) UIGestureRecognizer *interactivePopGestureRecognizer
83 |
84 | @end
85 |
86 | ```
87 | 我们看到,系统默认的手势是基于`UINavigationController`的,也就是说,手势是加在 `UINavigationController` 的 transitionView 上的,而且是只读的,我们无法篡改手势,以及无法定制手势,当然,这其中其他的问题,我们待会再说。
88 |
89 | 我们继续再看下系统默认的`Push`和`Pop`转场定制方案:
90 |
91 | #####默认转场方案
92 |
93 | * `UIViewControllerInteractiveTransitioning`
94 | 转场协议:虽然说是控制转场交互的,但是并没有达到字面意思上所具备动能。
95 |
96 | * `UIPercentDrivenInteractiveTransition`
97 | 转场进度控制器:系统默认提供的,通过百分比来控制转场的播放进度。
98 |
99 | ```
100 | // Code here
101 | // UINavigationControllerDelegate
102 | // 如果需要定制转场控制方案,需提供UIViewControllerInteractiveTransitioning实例,
103 | // 默认情况下不需要实现此代理,
104 |
105 | - (id)navigationController:(UINavigationController *)navigationController
106 | interactionControllerForAnimationController:(MDNavigationAnimationController *)animationController {
107 | return [UIPercentDrivenInteractiveTransition new];
108 | }
109 |
110 | ```
111 | ###默认动画方案
112 |
113 | * `UIViewControllerAnimatedTransitioning`
114 | 动画协议:当`Push`或者`Pop`动作发生后,会通过代理获取到该协议的具体动画实例。
115 |
116 | ```
117 | // Code here
118 | // UINavigationControllerDelegate
119 | // 如果需要定制动画方案,需提供UIViewControllerAnimatedTransitioning实例,
120 | // 默认情况下不需要实现此代理,
121 |
122 | - (id)navigationController:(UINavigationController *)navigationController
123 | animationControllerForOperation:(UINavigationControllerOperation)operation
124 | fromViewController:(UIViewController *)fromViewController
125 | toViewController:(UIViewController *)toViewController {
126 | if (operation == UINavigationControllerOperationPush) return push animation;
127 | if (operation == UINavigationControllerOperationPop) return pop animation;
128 | return nil;
129 | }
130 | ```
131 |
132 | 我再来看下`Present`、`Dismiss`,和`Push`、`Pop`类似
133 |
134 | ```
135 | // Code here
136 | - (id)animationControllerForPresentedController:(MDImageViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
137 | return present transitioning;
138 | }
139 | - (id)animationControllerForDismissedController:(MDImageViewController *)dismissed {
140 | return dismiss transitioning;
141 | }
142 | - (id)interactionControllerForPresentation:(id )animator;{
143 | return present interactive transitioning;
144 | }
145 | - (id)interactionControllerForDismissal:(id)animator;{
146 | return dismiss interactive transitioning;
147 | }
148 |
149 | ```
150 | 无论是`Present`、`Dismiss`、`Push`、`Pop`中的哪一种,都要遵从下面这个流程
151 |
152 |
153 | 由于基于系统的默认方案,我们会有以下三个问题:
154 |
155 | * 可以针对每个Controller定制动画,但是由于`UINavigationController`,`interactivePopGestureRecognizer`以及`transitioningDelegate`的局限性,在维护上相对离散,没有一个统一的方案;
156 | * 不可以针对每个Controller定制交互
157 | * 不可以针对每个Controller转场控制的
158 | * 对第三方动画和交互控制器的集成相对复杂
159 |
160 | ###所有我们准备提供一套完整的可扩展方案来解决这几个问题
161 |
162 | ### Why `MDTransitioning`?
163 |
164 | 基于上面的流程图来看,倘若我们需要针对每个转场进行定制,工作相对繁琐,维护困难。
165 | 所以`MDTransitioning`方案基于以下几个原则:
166 |
167 | * 交互:从谁那里来,就由谁提供
168 | * 动画:到哪里去,就由谁提供
169 | * 控制:谁触发,就由谁维护
170 |
171 | ###类关系
172 |
173 | ###动画类
174 |
175 |
176 | * MDViewControllerAnimatedTransitioning
177 |
178 | 基于`UIViewControllerAnimatedTransitioning`协议的再次封装,对关联的主从`View Controller`进行定义
179 |
180 | * `MDNavigationAnimatedTransitioning`
181 | 基于`MDViewControllerAnimatedTransitioning`协议的再次封装,定义`Push`和`Pop`的两种动画方式
182 |
183 | * `MDNavigationAnimationController`
184 | 基于`MDNavigationAnimatedTransitioning`协议的默认实现,默认实现`Push`和`Pop`动画,呈现方式和系统保持一致
185 |
186 | * `MPresentionAnimatedTransitioning`
187 | 基于`MDViewControllerAnimatedTransitioning`协议的再次封装,定义`Present`和`Dismiss`的两种动画方式
188 |
189 | * `MDPresentionAnimationController`
190 | 基于`MPresentionAnimatedTransitioning `协议的默认实现,默认实现`Present `和`Dismiss `动画,呈现方式和系统保持一致
191 |
192 | ###交互驱动类
193 |
194 | * `MDPercentDrivenInteractiveTransitioning`
195 | 基于系统UIViewControllerInteractiveTransitioning协议的再次封装,定义驱动所需的常规方法
196 |
197 | * `UIPercentDrivenInteractiveTransition`
198 | 系统提供的默认百分比驱动器,以便后期对驱动的扩展
199 |
200 | ###交互控制类
201 |
202 | * `MDInteractionController`
203 | 交互控制协议,负责控制交互的生命周期,手势变化,以及转场触发和进度维护
204 |
205 | * `MDSwipeInteractionController`
206 | 基于`MDInteractionController`协议的实现,实现对滑动手势交互的控制
207 |
208 | * `MDPopInteractionController`
209 | 基于`MDSwipeInteractionController`,提供`Pop`动作的滑动条件,以及进度计算
210 |
211 | * ``
212 | `Pop`动作控制器,默认由`UIViewController`实现,负责控制交互的加载条件、初始化、以及手势依赖的`UIView`
213 |
214 | * ``
215 | `Present`、`Dismiss`动作控制器,默认由`UIViewController`实现,负责控制Presention交互的加载条件、初始化、以及手势依赖的`UIView`
216 |
217 | ###优点
218 |
219 | * 提供一套默认的方案,和系统效果保持一致
220 | * 提供所有定制方案的底层类,轻轻松松就能完成自定义交互和动画的集成
221 | * 方便集成第三方动画和交互控制器,例如CE系列
222 | * 重点在这里,默认方案,**零写入**,**零入侵**
223 |
224 | ###到底有多简单?
225 |
226 | ****
227 |
228 | ### 案例一
229 |
230 | * `MDNavigationControllerDelegate `
231 | 为了方便接入,我们提供了默认的`Pop`和`Push`代理实现,只需要下面一行代码,就可以实现对系统转场的替换。
232 |
233 | ```
234 | // Code here
235 | navigationController.delegate = [MDNavigationControllerDelegate defaultDelegate];
236 |
237 | ```
238 | 效果和系统的保持一致
239 |
240 |
241 |
242 |
243 |
244 |
245 | ### 案例二
246 |
247 | * `MDPresentionControllerDelegate `
248 | 当然对于`Present`和`Dismiss`我们也提供了默认的代理实现,同样只需要下面一行代码对系统转场的替换。
249 |
250 | ```
251 | // Code here
252 | viewController.transitioningDelegate = [MDPresentionControllerDelegate delegateWithReferenceViewController:referenceViewController];
253 |
254 | ```
255 | 效果和系统的保持一致
256 |
257 |
258 |
259 |
260 | ### 为某个`View Contorller`定制一个缩放的`Pop`动画,但`Push`动画用默认的
261 |
262 | ```
263 | // Code here
264 | // 在将要显示的`View Contorller`内实现该方法,默认实现返回父类结果
265 | - (id)animationForNavigationOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController;{
266 | if (operation == UINavigationControllerOperationPush) {
267 | return [super animationForNavigationOperation:operation fromViewController:fromViewController toViewController:toViewController];
268 | } else {
269 | return [[MDScaleNavigationAnimationController alloc] initWithOperation:operation fromViewController:fromViewController toViewController:toViewController];
270 | }
271 | }
272 |
273 | ```
274 |
275 | ### 案例三
276 | ### 因为水平pop是默认实现的,所以我们调整一下,为某个`View Contorller`定制一个垂直滑动的`Pop`手势交互,虽然有点变态,但是这仅为测试
277 |
278 | ```
279 | // Code here
280 | // 在将要显示的`View Contorller`中复写该方法,提供垂直滑动的交互控制器
281 | - (id)requirePopInteractionController{
282 | return [MDVerticalSwipPopInteractionController interactionControllerWithViewController:self];
283 | }
284 |
285 | ```
286 | 效果如图:
287 |
288 |
289 |
290 | ### 案例四
291 |
292 | #### 为某个`View Contorller`定制一个图片放大的`Present`动画,但`Dismiss`动画用默认抽屉式的
293 |
294 | ```
295 | // Code here
296 | // 在将要显示的`View Contorller`内实现该方法,默认实现返回父类结果
297 | - (id)animationForPresentionOperation:(MDPresentionAnimatedOperation)operation fromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController;{
298 | if (operation == MDPresentionAnimatedOperationPresent) {
299 | MDImageZoomAnimationController *controller = [MDImageZoomAnimationController animationForPresentOperation:operation fromViewController:fromViewController toViewController:toViewController];
300 | controller.hideReferenceImageViewWhenZoomIn = NO;
301 | return controller;
302 | } else {
303 | return [[MDPresentionAnimationController alloc] initWithOperation:operation fromViewController:fromViewController toViewController:toViewController];
304 | }
305 | }
306 |
307 | ```
308 | ### 案例五
309 |
310 | ### 图片预览器,为某个`View Contorller`定制一个图片缩小的`Dismiss`手势交互
311 |
312 | ```
313 | // Code here
314 | // 在将要显示的`View Contorller`的`viewDidLoad`方法中添加交互控制器
315 | - (void)viewDidLoad {
316 | [super viewDidLoad];
317 |
318 | MDImageDraggingDismissInteractionController *interactionController = [MDImageDraggingDismissInteractionController interactionControllerWithViewController:self];
319 | interactionController.translation = 200.f;
320 |
321 | self.presentionInteractionController = interactionController;
322 | }
323 |
324 | ```
325 |
326 | 效果如图:
327 |
328 |
329 |
330 | ### 现成的动画和交互太少怎么办?
331 |
332 | 配合CE系列的动画和交互一起使用,我们提供CE的扩展方案MDTransitioning-VCTransitionsLibrary.
333 |
334 |
335 | ## 联系方式
336 |
337 | 

--------------------------------------------------------------------------------
/MDTransitioning.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/MDTransitioning.xcodeproj/xcshareddata/xcschemes/MDTransitioning.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
46 |
52 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
70 |
71 |
72 |
73 |
75 |
76 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/MDTransitioning.xcodeproj/xcshareddata/xcschemes/MDTransitioning_ImagePriview.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
46 |
52 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
70 |
71 |
72 |
73 |
75 |
76 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/MDTransitioning.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/MDTransitioning.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/MDTransitioning/MDAnimatedTransitioning.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import
22 |
23 | @protocol MDInteractionController;
24 |
25 | // This is baseic protocol of animated transitioning, extend to access view controllers in transition view.
26 | @protocol MDViewControllerAnimatedTransitioning
27 |
28 | // The duration of animation.
29 | @property (nonatomic, assign) NSTimeInterval duration;
30 |
31 | // Access appearing view controller in transition view.
32 | @property (nonatomic, weak, readonly) UIViewController *fromViewController;
33 |
34 | // Access view controller will be appearing in transition view.
35 | @property (nonatomic, weak, readonly) UIViewController *toViewController;
36 |
37 | @end
38 |
39 | // This is navigation transitioning protocol, extend to access operation.
40 | @protocol MDNavigationAnimatedTransitioning
41 |
42 | // Access operation, push or pop.
43 | @property (nonatomic, assign, readonly) UINavigationControllerOperation navigationControllerOperation;
44 |
45 | /**
46 | The designated initializer. If you subclass MDNavigationAnimationController, you must call the super implementation of this
47 | method.
48 |
49 | @param navigationControllerOperation navigation controller operation, push or pop.
50 | @param fromViewController view controller appearing.
51 | @param toViewController view controller will be appearing.
52 | @return an instance of MDNavigationAnimationController or sub class.
53 | */
54 | - (instancetype)initWithNavigationControllerOperation:(UINavigationControllerOperation)navigationControllerOperation fromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController;
55 |
56 | @end
57 |
58 | // Enum of presention operations, present and dismiss.
59 | typedef NS_ENUM(NSInteger, MDPresentionAnimatedOperation) {
60 | MDPresentionAnimatedOperationNone,
61 | MDPresentionAnimatedOperationPresent,
62 | MDPresentionAnimatedOperationDismiss,
63 | };
64 |
65 | // This is presention transitioning protocol, extend to access operation.
66 | @protocol MPresentionAnimatedTransitioning
67 |
68 | // Access operation, present or dismiss.
69 | @property (nonatomic, assign, readonly) MDPresentionAnimatedOperation presentionAnimatedOperation;
70 |
71 | /**
72 | The designated initializer. If you subclass MDNavigationAnimationController, you must call the super implementation of this
73 | method.
74 |
75 | @param presentionAnimatedOperation presention controller operation, present or dismiss.
76 | @param fromViewController view controller appearing.
77 | @param toViewController view controller will be appearing.
78 | @return an instance of MDPresentionAnimationController or sub class.
79 | */
80 | - (instancetype)initWithPresentionAnimatedOperation:(MDPresentionAnimatedOperation)presentionAnimatedOperation fromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController;
81 |
82 | @end
83 |
84 |
85 |
--------------------------------------------------------------------------------
/MDTransitioning/MDInteractionController.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import "MDAnimatedTransitioning.h"
22 | #import "MDInteractiveTransitioning.h"
23 |
24 | // This is interaction controller control, control interaction of gesture
25 | // and progress of interactive transition, the gesture will be added in view of view controller,
26 | // Needs to care conflict for gestures if overrides.
27 | @protocol MDInteractionController
28 |
29 | // The view controller with gesture.
30 | @property (nonatomic, weak, readonly) UIViewController *viewController;
31 |
32 | // The interactive transition, control progress animation.
33 | @property (nonatomic, strong, readonly) id interactiveTransition;
34 |
35 | // The current interaction state.
36 | @property (nonatomic, assign, readonly) BOOL interactionInProgress;
37 |
38 | // To control ability of gesture.
39 | @property (nonatomic, assign) BOOL enable;
40 |
41 | // To control ability of gesture dynamic.
42 | @property (nonatomic, copy) CGFloat (^allowSwipe)(CGPoint location, CGPoint velocity);
43 |
44 | // To provide progress with location, translation and velocity.
45 | @property (nonatomic, copy) CGFloat (^progress)(CGPoint location, CGPoint translation, CGPoint velocity);
46 |
47 | // It‘s called after begginning of gesture.
48 | @property (nonatomic, copy) void (^begin)(id interactiveTransition); // Default is called requireInteractiveTransition.
49 |
50 | // It‘s called after end of gesture.
51 | @property (nonatomic, copy) void (^end)(id interactiveTransition, BOOL finished);
52 |
53 | // It‘s called after updating progress of gesture.
54 | @property (nonatomic, copy) void (^update)(id interactiveTransition, CGFloat progress);
55 |
56 | /**
57 | Require an interactive transition base on percent driven.
58 |
59 | @return an instance base on protocol MDPercentDrivenInteractiveTransitioning, default is UIPercentDrivenInteractiveTransition.
60 | */
61 | - (id)requireInteractiveTransition;
62 |
63 | + (instancetype)interactionControllerWithViewController:(UIViewController *)viewController;
64 | - (instancetype)initWithViewController:(UIViewController *)viewController;
65 |
66 | @end
67 |
68 | // This is navigation controller with pop interaction, contain an interaction controler
69 | // and animation provider.
70 | @protocol MDNavigationPopController
71 |
72 | // Snapshot is created before view controller is disappearing.
73 | @property (nonatomic, strong) UIView *snapshot;
74 | @property (nonatomic, strong) UIView *navigationBarSnapshot;
75 |
76 | // Interaction controller control both geture and transitioning progress.
77 | @property (nonatomic, strong) id interactionController;
78 |
79 | // The interaction controller is invalid if it's NO, default is YES.
80 | @property (nonatomic, assign) BOOL allowPopInteractive;
81 |
82 | // Needs to provide an interaction controller without inner control if it's YES,
83 | // and needs to control outside gesture, default is NO.
84 | @property (nonatomic, assign) BOOL allowCustomPopInteractive;
85 |
86 | /**
87 | Require an pop interaction controller.
88 |
89 | @return an instance base on protocol MDInteractionController, default is MDPopInteractionController.
90 | */
91 | - (id)requirePopInteractionController;
92 |
93 | /**
94 | Provide an navigation transitioning, ignored push interaction.
95 |
96 | @param operation navigation controller operation, push or pop.
97 | @param fromViewController view controller appearing.
98 | @param toViewController view controller will be appearing.
99 | @return an instance of animated transitioning, default is MDNavigationAnimationController.
100 | */
101 | - (id)animationForNavigationOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController;
102 |
103 | @end
104 |
105 | // This is presention controller with present or dismiss interaction,
106 | // also contain an interaction controler and animation provider.
107 | @protocol MDPresentionController
108 |
109 | // Interaction controller control both geture and transitioning progress.
110 | @property (nonatomic, strong) id presentionInteractionController;
111 |
112 | /**
113 | Provide an presention transitioning.
114 |
115 | @param operation presention controller operation, presnt or dismiss.
116 | @param fromViewController view controller appearing.
117 | @param toViewController view controller will be appearing.
118 | @return an instance of animated transitioning, default is MDPresentionAnimationController.
119 | */
120 | - (id)animationForPresentionOperation:(MDPresentionAnimatedOperation)operation fromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController;
121 |
122 | @end
123 |
--------------------------------------------------------------------------------
/MDTransitioning/MDInteractiveTransitioning.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import
22 |
23 | // This is baseic protocol of interactive transitioning, interactive progress base on percent.
24 | @protocol MDPercentDrivenInteractiveTransitioning
25 |
26 | // Duration of transitioning.
27 | @property (nonatomic, assign, readonly) CGFloat duration;
28 |
29 | // Current completed percent of transition.
30 | @property (nonatomic, assign, readonly) CGFloat percentComplete;
31 |
32 | // Pause playing transition.
33 | - (void)pauseInteractiveTransition NS_AVAILABLE_IOS(10_0);
34 |
35 | // Update progress of playing transition.
36 | - (void)updateInteractiveTransition:(CGFloat)percentComplete;
37 |
38 | // Cancel playing transition.
39 | - (void)cancelInteractiveTransition;
40 |
41 | // Finish playing transition.
42 | - (void)finishInteractiveTransition;
43 |
44 | @end
45 |
46 | // System interactive transition
47 | @interface UIPercentDrivenInteractiveTransition (MDPercentDrivenInteractiveTransitioning)
48 | @end
49 |
--------------------------------------------------------------------------------
/MDTransitioning/MDNavigationAnimationController.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import
22 | #import "MDAnimatedTransitioning.h"
23 |
24 | // The default navigation animation controller base on MDNavigationAnimatedTransitioning
25 | @interface MDNavigationAnimationController : NSObject
26 |
27 | // The duration of animation, default is 0.25f.
28 | @property (nonatomic, assign) NSTimeInterval duration;
29 |
30 | // The duration of animation, default is 0.25f.
31 | @property (nonatomic, assign, getter=isSnapshotEnabled) BOOL snapshotEnable;
32 |
33 | /**
34 | The designated initializer. If you subclass MDNavigationAnimationController, you must call the super implementation of this
35 | method.
36 |
37 | @param navigationControllerOperation navigation controller operation, push or pop.
38 | @param fromViewController view controller appearing.
39 | @param toViewController view controller will be appearing.
40 | @return an instance of MDNavigationAnimationController or sub class.
41 | */
42 | - (instancetype)initWithNavigationControllerOperation:(UINavigationControllerOperation)navigationControllerOperation fromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController;
43 |
44 | - (instancetype)init DEPRECATED_MSG_ATTRIBUTE(" Use initWithOperation:fromViewController:toViewController: instead");
45 |
46 | @end
47 |
--------------------------------------------------------------------------------
/MDTransitioning/MDNavigationAnimationController.m:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import "MDNavigationAnimationController.h"
22 | #import "MDPopInteractionController.h"
23 | #import "UIViewController+MDNavigationTransitioning.h"
24 |
25 | @interface MDNavigationAnimationController ()
26 |
27 | @property (nonatomic, assign) UINavigationControllerOperation navigationControllerOperation;
28 | @property (nonatomic, weak) UIViewController *fromViewController;
29 | @property (nonatomic, weak) UIViewController *toViewController;
30 |
31 | @end
32 |
33 | @implementation MDNavigationAnimationController
34 |
35 | - (instancetype)init {
36 | return nil;
37 | }
38 |
39 | - (instancetype)initWithNavigationControllerOperation:(UINavigationControllerOperation)navigationControllerOperation fromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController {
40 | self = [super init];
41 | if (self) {
42 | self.duration = 0.25;
43 | self.navigationControllerOperation = navigationControllerOperation;
44 | self.fromViewController = fromViewController;
45 | self.toViewController = toViewController;
46 | self.snapshotEnable = YES;
47 | }
48 | return self;
49 | }
50 |
51 | - (NSTimeInterval)transitionDuration:(id)transitioning {
52 | return [self navigationControllerOperation] == UINavigationControllerOperationPush ? 0.35f : [self duration];
53 | }
54 |
55 | - (void)animateTransition:(id )transitionContext; {
56 | if ([self navigationControllerOperation] == UINavigationControllerOperationPush) {
57 | [self pushTransitioning:transitionContext];
58 | } else {
59 | [self popTransitioning:transitionContext];
60 | }
61 | }
62 |
63 | - (void)pushTransitioning:(id)transitioning {
64 | UIViewController *fromViewController = [transitioning viewControllerForKey:UITransitionContextFromViewControllerKey];
65 | UIViewController *toViewController = [transitioning viewControllerForKey:UITransitionContextToViewControllerKey];
66 |
67 | NSTimeInterval duration = [self transitionDuration:transitioning];
68 |
69 | CGRect initialFrame = [transitioning initialFrameForViewController:fromViewController];
70 | CGRect finalFrame = [transitioning finalFrameForViewController:toViewController];
71 | CGRect fromViewDestination = CGRectOffset(initialFrame, -CGRectGetWidth(initialFrame) / 2., 0);
72 |
73 | UIView *overlayer = [[UIView alloc] initWithFrame:(CGRect){0, 0, initialFrame.size}];
74 | overlayer.alpha = 0;
75 | overlayer.backgroundColor = [UIColor colorWithWhite:0 alpha:.2f];
76 |
77 | UIView *fromView = [self isSnapshotEnabled] ? [fromViewController snapshot] : [fromViewController view];
78 |
79 | fromViewController.view.hidden = [self isSnapshotEnabled];
80 | toViewController.view.frame = CGRectOffset(finalFrame, CGRectGetWidth(finalFrame), 0);
81 |
82 | [fromView addSubview:overlayer];
83 | [[transitioning containerView] addSubview:fromView];
84 | [[transitioning containerView] addSubview:[toViewController view]];
85 |
86 | [UIView animateWithDuration:duration
87 | delay:0.f
88 | options:UIViewAnimationOptionCurveEaseOut
89 | animations:^{
90 | overlayer.alpha = 1.f;
91 | fromView.frame = fromViewDestination;
92 | toViewController.view.frame = finalFrame;
93 | }
94 | completion:^(BOOL finished) {
95 | toViewController.view.frame = finalFrame;
96 | fromViewController.view.frame = initialFrame;
97 | fromViewController.view.hidden = NO;
98 |
99 | [fromView removeFromSuperview];
100 | [overlayer removeFromSuperview];
101 |
102 | [transitioning completeTransition:![transitioning transitionWasCancelled]];
103 | }];
104 | }
105 |
106 | - (void)popTransitioning:(id)transitioning {
107 | UIViewController *fromViewController = [transitioning viewControllerForKey:UITransitionContextFromViewControllerKey];
108 | UIViewController *toViewController = [transitioning viewControllerForKey:UITransitionContextToViewControllerKey];
109 |
110 | NSTimeInterval duration = [self transitionDuration:transitioning];
111 |
112 | CGRect initialFrame = [transitioning initialFrameForViewController:fromViewController];
113 | CGRect finalFrame = [transitioning finalFrameForViewController:toViewController];
114 | CGRect toViewOrigin = CGRectOffset(finalFrame, -CGRectGetWidth(finalFrame) / 2., 0);;
115 | CGRect fromViewDestination = CGRectOffset(finalFrame, CGRectGetWidth(finalFrame), 0);
116 |
117 | toViewController.view.frame = toViewOrigin;
118 | fromViewController.view.hidden = [self isSnapshotEnabled];
119 |
120 | UIView *fromView = [self isSnapshotEnabled] ? [fromViewController snapshot] : [fromViewController view];
121 | fromView.frame = initialFrame;
122 |
123 | UIView *overlayer = [[UIView alloc] initWithFrame:(CGRect){0, 0, finalFrame.size}];
124 | overlayer.backgroundColor = [UIColor colorWithWhite:0 alpha:.2f];
125 |
126 | [[toViewController view] addSubview:overlayer];
127 | [[transitioning containerView] addSubview:[toViewController view]];
128 | [[transitioning containerView] addSubview:fromView];
129 | [[transitioning containerView] bringSubviewToFront:fromView];
130 |
131 | [UIView animateWithDuration:duration
132 | delay:0.0
133 | options:UIViewAnimationOptionCurveLinear
134 | animations:^{
135 | overlayer.alpha = 0;
136 | fromView.frame = fromViewDestination;
137 | toViewController.view.frame = finalFrame;
138 | }
139 | completion:^(BOOL finished) {
140 | toViewController.view.frame = finalFrame;
141 | fromViewController.view.frame = initialFrame;
142 | fromViewController.view.hidden = NO;
143 |
144 | [fromView removeFromSuperview];
145 | [overlayer removeFromSuperview];
146 | // Reset toViewController's `snapshot` to nil
147 | if ([transitioning transitionWasCancelled]) {
148 | [[toViewController view] removeFromSuperview];
149 | } else {
150 | toViewController.snapshot = nil;
151 | }
152 | [transitioning completeTransition:![transitioning transitionWasCancelled]];
153 | }];
154 | }
155 |
156 | @end
157 |
--------------------------------------------------------------------------------
/MDTransitioning/MDNavigationControllerDelegate.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import
22 |
23 | @interface UINavigationController (MDPushAnimation)
24 |
25 | @property (nonatomic, assign) BOOL allowPushAnimation;
26 |
27 | @end
28 |
29 | // The default delegate of UINavigationControllerDelegate, to provide default implementation.
30 | @interface MDNavigationControllerDelegate : NSObject
31 |
32 | + (instancetype)defaultDelegate;
33 |
34 | @end
35 |
--------------------------------------------------------------------------------
/MDTransitioning/MDNavigationControllerDelegate.m:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import
22 |
23 | #import "MDNavigationControllerDelegate.h"
24 | #import "MDNavigationAnimationController.h"
25 | #import "MDInteractionController.h"
26 | #import "UIViewController+MDNavigationTransitioning.h"
27 | #import "MDTransitioning+Private.h"
28 |
29 | @implementation UINavigationController (MDNavigationAnimationController)
30 |
31 | + (void)load{
32 | static dispatch_once_t onceToken;
33 | dispatch_once(&onceToken, ^{
34 | MDTransitioningMethodSwizzle([self class], @selector(pushViewController:animated:), @selector(swizzle_pushViewController:animated:));
35 | });
36 | }
37 |
38 | - (void)swizzle_pushViewController:(UIViewController*)viewController animated:(BOOL)animated{
39 | if ([self delegate] == [MDNavigationControllerDelegate defaultDelegate]) {
40 | self.view.userInteractionEnabled = NO;
41 |
42 | if ([self topViewController] && ![[self topViewController] snapshot]) {
43 | self.topViewController.snapshot = [[self view] snapshotViewAfterScreenUpdates:NO];
44 | }
45 | }
46 |
47 | [self swizzle_pushViewController:viewController animated:animated];
48 | }
49 |
50 | - (BOOL)allowPushAnimation{
51 | return [objc_getAssociatedObject(self, @selector(allowPushAnimation)) boolValue];
52 | }
53 |
54 | - (void)setAllowPushAnimation:(BOOL)allowPushAnimation{
55 | objc_setAssociatedObject(self, @selector(allowPushAnimation), @(allowPushAnimation), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
56 | }
57 |
58 | @end
59 |
60 | @implementation MDNavigationControllerDelegate
61 |
62 | + (instancetype)defaultDelegate;{
63 | static MDNavigationControllerDelegate *delegate = nil;
64 | static dispatch_once_t onceToken;
65 | dispatch_once(&onceToken, ^{
66 | delegate = [MDNavigationControllerDelegate new];
67 | });
68 | return delegate;
69 | }
70 |
71 | #pragma mark UINavigationControllerDelegate
72 |
73 | - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animate{
74 | navigationController.view.userInteractionEnabled = YES;
75 | }
76 |
77 | - (id)navigationController:(UINavigationController *)navigationController
78 | interactionControllerForAnimationController:(MDNavigationAnimationController *)animationController {
79 | return [[[animationController fromViewController] interactionController] interactiveTransition];
80 | }
81 |
82 | - (id)navigationController:(UINavigationController *)navigationController
83 | animationControllerForOperation:(UINavigationControllerOperation)operation
84 | fromViewController:(UIViewController *)fromViewController
85 | toViewController:(UIViewController *)toViewController {
86 | if (operation == UINavigationControllerOperationPush && ![navigationController allowPushAnimation]) return nil;
87 | UIViewController *displayingViewController = operation == UINavigationControllerOperationPush ? toViewController : fromViewController;
88 | return [displayingViewController animationForNavigationOperation:operation fromViewController:fromViewController toViewController:toViewController];
89 | }
90 |
91 | @end
92 |
--------------------------------------------------------------------------------
/MDTransitioning/MDPopInteractionController.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import
22 | #import "MDSwipeInteractionController.h"
23 |
24 | // The controller of pop interaction.
25 | @interface MDPopInteractionController : MDSwipeInteractionController
26 |
27 | // The horizontal offset is left edge of content view, default is 20.f.
28 | @property (nonatomic, assign) CGFloat horizontalOffset;
29 |
30 | @end
31 |
--------------------------------------------------------------------------------
/MDTransitioning/MDPopInteractionController.m:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import "MDPopInteractionController.h"
22 |
23 | @implementation MDPopInteractionController
24 |
25 | - (instancetype)initWithViewController:(UIViewController *)viewController{
26 | if (self = [super initWithViewController:viewController]) {
27 | __block __weak id weak_self = self;
28 | self.horizontalOffset = 20.f;
29 | self.begin = ^(id interactiveTransition){
30 | [[viewController navigationController] popViewControllerAnimated:YES];
31 | };
32 | self.allowSwipe = ^CGFloat(CGPoint location, CGPoint velocity) {
33 | return velocity.x > 0 && location.x < [weak_self horizontalOffset];
34 | };
35 | self.progress = ^CGFloat(CGPoint location, CGPoint translation, CGPoint velocity) {
36 | return translation.x / CGRectGetWidth([[viewController view] frame]);
37 | };
38 | }
39 | return self;
40 | }
41 |
42 | @end
43 |
--------------------------------------------------------------------------------
/MDTransitioning/MDPresentionAnimationController.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import
22 | #import "MDAnimatedTransitioning.h"
23 |
24 | // The default presention animation controller base on MPresentionAnimatedTransitioning
25 | @interface MDPresentionAnimationController : NSObject
26 |
27 | // The duration of animation, default is 0.25f.
28 | @property (nonatomic, assign) NSTimeInterval duration; // Default is 0.25f.
29 |
30 | /**
31 | The designated initializer. If you subclass MDNavigationAnimationController, you must call the super implementation of this
32 | method.
33 |
34 | @param presentionAnimatedOperation presention controller operation, present or dismiss.
35 | @param fromViewController view controller appearing.
36 | @param toViewController view controller will be appearing.
37 | @return an instance of MDPresentionAnimationController or sub class.
38 | */
39 | - (instancetype)initWithPresentionAnimatedOperation:(MDPresentionAnimatedOperation)presentionAnimatedOperation fromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController;
40 |
41 | - (instancetype)init DEPRECATED_MSG_ATTRIBUTE(" Use initWithOperation:fromViewController:toViewController: instead");
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/MDTransitioning/MDPresentionAnimationController.m:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import "MDPresentionAnimationController.h"
22 | #import "UIViewController+MDPresentionTransitioning.h"
23 |
24 | @interface MDPresentionAnimationController ()
25 |
26 | @property (nonatomic, assign) MDPresentionAnimatedOperation presentionAnimatedOperation;
27 | @property (nonatomic, weak) UIViewController *fromViewController;
28 | @property (nonatomic, weak) UIViewController *toViewController;
29 |
30 | @end
31 |
32 | @implementation MDPresentionAnimationController
33 |
34 | - (instancetype)init {
35 | return nil;
36 | }
37 |
38 | - (instancetype)initWithPresentionAnimatedOperation:(MDPresentionAnimatedOperation)presentionAnimatedOperation fromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController {
39 | self = [super init];
40 | if (self) {
41 | NSParameterAssert(presentionAnimatedOperation != MDPresentionAnimatedOperationNone);
42 |
43 | self.duration = 0.25;
44 | self.presentionAnimatedOperation = presentionAnimatedOperation;
45 | self.fromViewController = fromViewController;
46 | self.toViewController = toViewController;
47 | }
48 | return self;
49 | }
50 |
51 | - (NSTimeInterval)transitionDuration:(id)transitioning {
52 | return [self duration];
53 | }
54 |
55 | - (void)animateTransition:(id)transitioning {
56 | if ([self presentionAnimatedOperation] == MDPresentionAnimatedOperationPresent) {
57 | [self presentTransitioning:transitioning];
58 | } else {
59 | [self dismissTransitioning:transitioning];
60 | }
61 | }
62 |
63 | - (void)presentTransitioning:(id)transitioning {
64 | UIViewController *fromViewController = [transitioning viewControllerForKey:UITransitionContextFromViewControllerKey];
65 | UIViewController *toViewController = [transitioning viewControllerForKey:UITransitionContextToViewControllerKey];
66 |
67 | CGRect initialFrame = [transitioning initialFrameForViewController:fromViewController];
68 | CGRect finalFrame = [transitioning finalFrameForViewController:toViewController];
69 | CGRect origin = CGRectOffset(initialFrame, 0, CGRectGetHeight(finalFrame));
70 |
71 | toViewController.view.frame = origin;
72 | [[transitioning containerView] addSubview:[toViewController view]];
73 |
74 | NSTimeInterval duration = [self transitionDuration:transitioning];
75 | [UIView animateWithDuration:duration
76 | delay:0.0
77 | options:UIViewAnimationOptionCurveEaseIn
78 | animations:^{
79 | toViewController.view.frame = finalFrame;
80 | }
81 | completion:^(BOOL finished) {
82 | [transitioning completeTransition:YES];
83 | }];
84 | }
85 |
86 | - (void)dismissTransitioning:(id)transitioning {
87 | UIViewController *fromViewController = [transitioning viewControllerForKey:UITransitionContextFromViewControllerKey];
88 | UIViewController *toViewController = [transitioning viewControllerForKey:UITransitionContextToViewControllerKey];
89 |
90 | CGRect initialFrame = [transitioning initialFrameForViewController:fromViewController];
91 | CGRect finalFrame = [transitioning finalFrameForViewController:toViewController];
92 | CGRect destination = CGRectOffset(initialFrame, 0, CGRectGetHeight(finalFrame));
93 |
94 | [[transitioning containerView] addSubview:[toViewController view]];
95 | [[transitioning containerView] sendSubviewToBack:[toViewController view]];
96 |
97 | NSTimeInterval duration = [self transitionDuration:transitioning];
98 | [UIView animateWithDuration:duration
99 | delay:0.0
100 | options:UIViewAnimationOptionCurveEaseOut
101 | animations:^{
102 | fromViewController.view.frame = destination;
103 | }
104 | completion:^(BOOL finished) {
105 | fromViewController.view.frame = initialFrame;
106 |
107 | if ([transitioning transitionWasCancelled]) {
108 | [[toViewController view] removeFromSuperview];
109 | }
110 |
111 | [transitioning completeTransition:![transitioning transitionWasCancelled]];
112 | }];
113 | }
114 |
115 | @end
116 |
--------------------------------------------------------------------------------
/MDTransitioning/MDPresentionControllerDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // MDPresentionControllerDelegate.h
3 | // MDTransitioning
4 | //
5 | // Created by 徐 林峰 on 2017/9/20.
6 | // Copyright © 2017年 markejave. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface MDPresentionControllerDelegate : NSObject
12 |
13 | @property (nonatomic, weak, readonly) UIViewController *referenceViewController;
14 |
15 | + (instancetype)delegateWithReferenceViewController:(UIViewController *)viewController;
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/MDTransitioning/MDPresentionControllerDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // MDPresentionControllerDelegate.m
3 | // MDTransitioning
4 | //
5 | // Created by 徐 林峰 on 2017/9/20.
6 | // Copyright © 2017年 markejave. All rights reserved.
7 | //
8 |
9 | #import "MDPresentionControllerDelegate.h"
10 | #import "UIViewController+MDPresentionTransitioning.h"
11 |
12 | @interface MDPresentionControllerDelegate ()
13 |
14 | @property (nonatomic, weak) UIViewController *referenceViewController;
15 |
16 | @end
17 |
18 | @implementation MDPresentionControllerDelegate
19 |
20 | + (MDPresentionControllerDelegate *)delegateWithReferenceViewControllerClass:(Class)referenceViewControllerClass{
21 | static NSMutableDictionary *delegates = nil;
22 | static dispatch_once_t onceToken;
23 | dispatch_once(&onceToken, ^{
24 | delegates = [NSMutableDictionary new];
25 | });
26 | NSString *key = NSStringFromClass(referenceViewControllerClass);
27 | MDPresentionControllerDelegate *delegate = delegates[key];
28 | if (!delegate) {
29 | delegate = [MDPresentionControllerDelegate new];
30 | delegates[key] = delegate;
31 | }
32 | return delegate;
33 | }
34 |
35 | + (instancetype)delegateWithReferenceViewController:(UIViewController *)viewController;{
36 | MDPresentionControllerDelegate *delegate = [self delegateWithReferenceViewControllerClass:[viewController class]];
37 | delegate.referenceViewController = viewController;
38 | return delegate;
39 | }
40 |
41 | #pragma mark - UIViewControllerTransitioningDelegate
42 |
43 | - (id)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
44 | return [presented animationForPresentionOperation:MDPresentionAnimatedOperationPresent fromViewController:[self referenceViewController] toViewController:presented];
45 | }
46 |
47 | - (id)animationControllerForDismissedController:(UIViewController *)dismissed {
48 | return [dismissed animationForPresentionOperation:MDPresentionAnimatedOperationDismiss fromViewController:dismissed toViewController:[self referenceViewController]];
49 | }
50 |
51 | //- (nullable id )interactionControllerForPresentation:(id )animator;{
52 | // return [[[animator fromViewController] presentionInteractionController] interactiveTransition];
53 | //}
54 |
55 | - (id )interactionControllerForDismissal:(id)animator;{
56 | return [[[animator fromViewController] presentionInteractionController] interactiveTransition];
57 | }
58 |
59 |
60 | @end
61 |
--------------------------------------------------------------------------------
/MDTransitioning/MDScaleNavigationAnimationController.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import
22 |
23 | @interface MDScaleNavigationAnimationController : MDNavigationAnimationController
24 |
25 | @property (nonatomic, assign, getter=isSnapshotEnabled) BOOL snapshotEnable NS_UNAVAILABLE;
26 |
27 | // The offset to scale based on transition view frame.
28 | @property (nonatomic, assign) CGSize scaleOffset;
29 |
30 | // The background color of transion view will be changed, both push and pop.
31 | @property (nonatomic, strong) UIColor *transitionBackgroundColor;
32 |
33 | // The background color of transion view when pushing.
34 | @property (nonatomic, strong) UIColor *pushTransitionBackgroundColor;
35 |
36 | // The background color of transion view when popping.
37 | @property (nonatomic, strong) UIColor *popTransitionBackgroundColor;
38 |
39 | @end
40 |
--------------------------------------------------------------------------------
/MDTransitioning/MDScaleNavigationAnimationController.m:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import "MDScaleNavigationAnimationController.h"
22 |
23 | @implementation MDScaleNavigationAnimationController
24 | @dynamic snapshotEnable;
25 |
26 | - (instancetype)initWithNavigationControllerOperation:(UINavigationControllerOperation)navigationControllerOperation fromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController{
27 | if (self = [super initWithNavigationControllerOperation:navigationControllerOperation fromViewController:fromViewController toViewController:toViewController]) {
28 | self.scaleOffset = CGSizeMake(20, 20);
29 | self.transitionBackgroundColor = [UIColor blackColor];
30 | }
31 | return self;
32 | }
33 |
34 | - (void)setTransitionBackgroundColor:(UIColor *)transitionBackgroundColor{
35 | _transitionBackgroundColor = transitionBackgroundColor;
36 |
37 | self.pushTransitionBackgroundColor = transitionBackgroundColor;
38 | self.popTransitionBackgroundColor = transitionBackgroundColor;
39 | }
40 |
41 | - (void)setPushTransitionBackgroundColor:(UIColor *)pushTransitionBackgroundColor{
42 | if (_pushTransitionBackgroundColor != pushTransitionBackgroundColor) {
43 | _pushTransitionBackgroundColor = pushTransitionBackgroundColor;
44 |
45 | if (_pushTransitionBackgroundColor != _transitionBackgroundColor) {
46 | _transitionBackgroundColor = nil;
47 | }
48 | }
49 | }
50 |
51 | - (void)setPopTransitionBackgroundColor:(UIColor *)popTransitionBackgroundColor{
52 | if (_popTransitionBackgroundColor != popTransitionBackgroundColor) {
53 | _popTransitionBackgroundColor = popTransitionBackgroundColor;
54 |
55 | if (popTransitionBackgroundColor != _transitionBackgroundColor) {
56 | _transitionBackgroundColor = nil;
57 | }
58 | }
59 | }
60 |
61 | - (void)pushTransitioning:(id)transitioning {
62 | UIViewController *fromViewController = [transitioning viewControllerForKey:UITransitionContextFromViewControllerKey];
63 | UIViewController *toViewController = [transitioning viewControllerForKey:UITransitionContextToViewControllerKey];
64 |
65 | NSTimeInterval duration = [self transitionDuration:transitioning];
66 |
67 | CGRect initialFrame = [transitioning initialFrameForViewController:fromViewController];
68 | CGRect finalFrame = [transitioning finalFrameForViewController:toViewController];
69 | CGAffineTransform fromViewDestinationTransform = CGAffineTransformScale(CGAffineTransformIdentity, 1 - self.scaleOffset.width / CGRectGetWidth(initialFrame), 1 - self.scaleOffset.height / CGRectGetHeight(initialFrame));
70 |
71 | UIView *overlayer = [[UIView alloc] initWithFrame:(CGRect){0, 0, initialFrame.size}];
72 | overlayer.alpha = 0;
73 | overlayer.backgroundColor = [UIColor colorWithWhite:0 alpha:.2f];
74 |
75 | UIView *fromView = [fromViewController snapshot];
76 | fromViewController.view.hidden = YES;
77 |
78 | UINavigationBar *navigationBar = [[fromViewController navigationController] navigationBar];
79 | CGRect navigationBarFrame = [navigationBar frame];
80 |
81 | navigationBar.frame = CGRectOffset(navigationBarFrame, CGRectGetWidth(navigationBarFrame), 0);
82 | toViewController.view.frame = CGRectOffset(finalFrame, CGRectGetWidth(finalFrame), 0);
83 |
84 | [fromView addSubview:overlayer];
85 | [[transitioning containerView] addSubview:fromView];
86 | [[transitioning containerView] addSubview:[toViewController view]];
87 |
88 | UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
89 | UIColor *backgroundColor = [window backgroundColor];
90 |
91 | UITabBar *tabBar = fromViewController.tabBarController.tabBar;
92 | BOOL tabBarHidden = tabBar.hidden;
93 |
94 | tabBar.hidden = YES;
95 | window.backgroundColor = self.pushTransitionBackgroundColor;
96 | [UIView animateWithDuration:duration
97 | delay:0.f
98 | options:UIViewAnimationOptionCurveEaseOut
99 | animations:^{
100 | overlayer.alpha = 1.f;
101 | fromView.transform = fromViewDestinationTransform;
102 | toViewController.view.frame = finalFrame;
103 | navigationBar.frame = navigationBarFrame;
104 | }
105 | completion:^(BOOL finished) {
106 | fromView.transform = CGAffineTransformIdentity;
107 | navigationBar.frame = navigationBarFrame;
108 | toViewController.view.frame = finalFrame;
109 | fromViewController.view.frame = initialFrame;
110 |
111 | tabBar.hidden = tabBarHidden;
112 | fromViewController.view.hidden = NO;
113 |
114 | window.backgroundColor = backgroundColor;
115 |
116 | [fromView removeFromSuperview];
117 | [overlayer removeFromSuperview];
118 |
119 | [transitioning completeTransition:YES];
120 | }];
121 | }
122 |
123 | - (void)popTransitioning:(id)transitioning {
124 | UIViewController *fromViewController = [transitioning viewControllerForKey:UITransitionContextFromViewControllerKey];
125 | UIViewController *toViewController = [transitioning viewControllerForKey:UITransitionContextToViewControllerKey];
126 | NSTimeInterval duration = [self transitionDuration:transitioning];
127 |
128 | CGRect initialFrame = [transitioning initialFrameForViewController:fromViewController];
129 | CGRect finalFrame = [transitioning finalFrameForViewController:toViewController];
130 | CGRect fromViewDestination = CGRectOffset(initialFrame, CGRectGetWidth(initialFrame), 0);
131 | CGAffineTransform toViewOriginTransform = CGAffineTransformScale(CGAffineTransformIdentity, 1 - self.scaleOffset.width / CGRectGetWidth(finalFrame), 1 - self.scaleOffset.height / CGRectGetHeight(finalFrame));
132 |
133 | UIView *overlayer = [[UIView alloc] initWithFrame:(CGRect){0, 0, initialFrame.size}];
134 | overlayer.backgroundColor = [UIColor colorWithWhite:0 alpha:.2f];
135 |
136 | UIView *fromView = [fromViewController snapshot];
137 | fromViewController.view.hidden = YES;
138 |
139 | UIView *toView = [toViewController snapshot];
140 |
141 | [toView addSubview:overlayer];
142 | [[transitioning containerView] addSubview:[toViewController view]];
143 | [[transitioning containerView] addSubview:toView];
144 | [[transitioning containerView] addSubview:fromView];
145 | [[transitioning containerView] bringSubviewToFront:fromView];
146 |
147 | toView.transform = toViewOriginTransform;
148 | toViewController.view.hidden = YES;
149 |
150 | UITabBar *tabBar = fromViewController.tabBarController.tabBar;
151 | UINavigationBar *navigationBar = fromViewController.navigationController.navigationBar;
152 |
153 | BOOL tabBarHidden = tabBar.hidden;
154 | BOOL navigationBarHidden = navigationBar.hidden;
155 |
156 | tabBar.hidden = YES;
157 | navigationBar.hidden = YES;
158 |
159 | UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
160 | UIColor *backgroundColor = [window backgroundColor];
161 |
162 | window.backgroundColor = self.popTransitionBackgroundColor;
163 |
164 | [UIView animateWithDuration:duration
165 | delay:0.0
166 | options:UIViewAnimationOptionCurveLinear
167 | animations:^{
168 | overlayer.alpha = 0.f;
169 | fromView.frame = fromViewDestination;
170 | toView.transform = CGAffineTransformIdentity;
171 | }
172 | completion:^(BOOL finished) {
173 | toView.transform = CGAffineTransformIdentity;
174 | toViewController.view.frame = finalFrame;
175 | fromViewController.view.frame = initialFrame;
176 |
177 | window.backgroundColor = backgroundColor;
178 |
179 | tabBar.hidden = tabBarHidden;
180 | navigationBar.hidden = navigationBarHidden;
181 | toViewController.view.hidden = NO;
182 | fromViewController.view.hidden = NO;
183 |
184 | [overlayer removeFromSuperview];
185 | [toView removeFromSuperview];
186 |
187 | if ([transitioning transitionWasCancelled]) {
188 | [[toViewController view] removeFromSuperview];
189 | } else {
190 | [fromView removeFromSuperview];
191 | }
192 | [transitioning completeTransition:![transitioning transitionWasCancelled]];
193 | }];
194 | }
195 |
196 | @end
197 |
--------------------------------------------------------------------------------
/MDTransitioning/MDSwipeInteractionController.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import
22 | #import "MDInteractionController.h"
23 |
24 | // The controller of swipe interaction.
25 | @interface MDSwipeInteractionController : NSObject
26 |
27 | - (instancetype)init DEPRECATED_MSG_ATTRIBUTE(" Use interactionControllerWithViewController: instead");
28 |
29 | @end
30 |
--------------------------------------------------------------------------------
/MDTransitioning/MDSwipeInteractionController.m:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import "MDSwipeInteractionController.h"
22 |
23 | @interface MDSwipeInteractionController ()
24 |
25 | @property (nonatomic, assign) BOOL interactionInProgress;
26 |
27 | @property (nonatomic, weak) UIViewController *viewController;
28 |
29 | @property (nonatomic, strong) UIPanGestureRecognizer *panGestureRecognizer;
30 |
31 | @property (nonatomic, strong) id interactiveTransition;
32 |
33 | @end
34 |
35 | @implementation MDSwipeInteractionController
36 | @synthesize enable = _enable;
37 | @synthesize allowSwipe = _allowSwipe, progress = _progress;
38 | @synthesize begin = _begin, end = _end, update = _update;
39 |
40 | - (instancetype)init {
41 | return nil;
42 | }
43 |
44 | + (instancetype)interactionControllerWithViewController:(UIViewController *)viewController{
45 | return [[self alloc] initWithViewController:viewController];
46 | }
47 |
48 | - (instancetype)initWithViewController:(UIViewController *)viewController{
49 | if (self = [super init]) {
50 | self.viewController = viewController;
51 |
52 | [self prepareGestureRecognizerInView:[viewController view]];
53 | }
54 | return self;
55 | }
56 |
57 | #pragma mark - accessor
58 |
59 | - (void)setEnable:(BOOL)enable{
60 | self.panGestureRecognizer.enabled = enable;
61 | }
62 |
63 | - (BOOL)enable{
64 | return [[self panGestureRecognizer] isEnabled];
65 | }
66 |
67 | #pragma mark - protected
68 |
69 | - (id)requireInteractiveTransition;{
70 | return [UIPercentDrivenInteractiveTransition new];
71 | }
72 |
73 | - (void)prepareGestureRecognizerInView:(UIView*)view {
74 | self.panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGestureRecognizer:)];
75 | self.panGestureRecognizer.delegate = self;
76 | [view addGestureRecognizer:[self panGestureRecognizer]];
77 | }
78 |
79 | #pragma mark - UIPanGestureRecognizer handlers
80 |
81 | - (void)handlePanGestureRecognizer:(UIPanGestureRecognizer *)recognizer {
82 | CGPoint location = [recognizer locationInView:[[self viewController] view]];
83 | CGPoint translation = [recognizer translationInView:[[self viewController] view]];
84 | CGPoint velocity = [recognizer velocityInView:[[self viewController] view]];
85 |
86 | if ([recognizer state] == UIGestureRecognizerStateBegan) {
87 | self.interactionInProgress = YES;
88 | // Create a interactive transition and pop the view controller
89 | self.interactiveTransition = [self requireInteractiveTransition];
90 | if ([self begin]) {
91 | self.begin([self interactiveTransition]);
92 | }
93 | } else if ([recognizer state] == UIGestureRecognizerStateChanged) {
94 | CGFloat progress = [self progress] ? self.progress(location, translation, velocity) : 1.f;
95 | progress = MIN(1.0, MAX(0.0, progress));
96 | // Update the interactive transition's progress
97 | if ([self update]) {
98 | self.update([self interactiveTransition], progress);
99 | }
100 | [[self interactiveTransition] updateInteractiveTransition:progress];
101 | } else if ([recognizer state] == UIGestureRecognizerStateEnded || [recognizer state] == UIGestureRecognizerStateCancelled) {
102 | CGFloat progress = [self progress] ? self.progress(location, translation, velocity) : 1.f;
103 | progress = MIN(1.0, MAX(0.0, progress));
104 | // Finish or cancel the interactive transition
105 | if (progress > 0.25) {
106 | [[self interactiveTransition] finishInteractiveTransition];
107 | } else {
108 | [[self interactiveTransition] cancelInteractiveTransition];
109 | }
110 | if ([self end]) {
111 | self.end([self interactiveTransition], progress > 0.25);
112 | }
113 | self.interactiveTransition = nil;
114 | self.interactionInProgress = NO;
115 | }
116 | }
117 |
118 | #pragma mark - UIGestureRecognizerDelegate
119 |
120 | - (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)recognizer {
121 | CGPoint location = [recognizer locationInView:[[self viewController] view]];
122 | CGPoint velocety = [recognizer velocityInView:[[self viewController] view]];
123 |
124 | return recognizer == [self panGestureRecognizer] && [self allowSwipe] && self.allowSwipe(location, velocety);
125 | }
126 |
127 | @end
128 |
--------------------------------------------------------------------------------
/MDTransitioning/MDTransitioning+Private.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import
22 | #import
23 |
24 | #ifndef MDTransitioningLoadCategory
25 | #define MDTransitioningLoadCategory(UNIQUE_NAME) @interface FORCELOAD_##UNIQUE_NAME :NSObject @end @implementation FORCELOAD_##UNIQUE_NAME @end
26 | #endif
27 |
28 | extern void MDTransitioningMethodSwizzle(Class class, SEL origSel, SEL altSel);
29 |
--------------------------------------------------------------------------------
/MDTransitioning/MDTransitioning+Private.m:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import "MDTransitioning+Private.h"
22 |
23 | void MDTransitioningMethodSwizzle(Class class, SEL origSel, SEL altSel) {
24 | Method origMethod = class_getInstanceMethod(class, origSel);
25 | Method altMethod = class_getInstanceMethod(class, altSel);
26 |
27 | class_addMethod(class, origSel, class_getMethodImplementation(class, origSel), method_getTypeEncoding(origMethod));
28 | class_addMethod(class, altSel, class_getMethodImplementation(class, altSel), method_getTypeEncoding(altMethod));
29 |
30 | method_exchangeImplementations(class_getInstanceMethod(class, origSel), class_getInstanceMethod(class, altSel));
31 | }
32 |
--------------------------------------------------------------------------------
/MDTransitioning/MDTransitioning.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import
22 |
23 | //! Project version number for MDTransitioning.
24 | FOUNDATION_EXPORT double MDTransitioningVersionNumber;
25 |
26 | //! Project version string for MDTransitioning.
27 | FOUNDATION_EXPORT const unsigned char MDTransitioningVersionString[];
28 |
29 | // In this header, you should import all the public headers of your framework using statements like #import
30 |
31 | #import
32 | #import
33 | #import
34 | #import
35 | #import
36 | #import
37 | #import
38 | #import
39 | #import
40 | #import
41 | #import
42 | #import
43 |
44 | #import
45 | #import
46 |
--------------------------------------------------------------------------------
/MDTransitioning/MDVerticalSwipDismissInteractionController.h:
--------------------------------------------------------------------------------
1 | //
2 | // MDVerticalSwipDismissInteractionController.h
3 | // MDTransitioning
4 | //
5 | // Created by xulinfeng on 2018/4/11.
6 | // Copyright © 2018年 markejave. All rights reserved.
7 | //
8 |
9 | #import "MDVerticalSwipInteractionController.h"
10 |
11 | @interface MDVerticalSwipDismissInteractionController : MDVerticalSwipInteractionController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/MDTransitioning/MDVerticalSwipDismissInteractionController.m:
--------------------------------------------------------------------------------
1 | //
2 | // MDVerticalSwipDismissInteractionController.m
3 | // MDTransitioning
4 | //
5 | // Created by xulinfeng on 2018/4/11.
6 | // Copyright © 2018年 markejave. All rights reserved.
7 | //
8 |
9 | #import "MDVerticalSwipDismissInteractionController.h"
10 |
11 | @implementation MDVerticalSwipDismissInteractionController
12 |
13 | - (instancetype)initWithViewController:(UIViewController *)viewController{
14 | if (self = [super initWithViewController:viewController]) {
15 | self.begin = ^(id interactiveTransition){
16 | [viewController dismissViewControllerAnimated:YES completion:nil];
17 | };
18 | }
19 | return self;
20 | }
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/MDTransitioning/MDVerticalSwipInteractionController.h:
--------------------------------------------------------------------------------
1 | //
2 | // MDVerticalSwipInteractionController.h
3 | // Demo
4 | //
5 | // Created by Jave on 2017/9/24.
6 | // Copyright © 2017年 markejave. All rights reserved.
7 | //
8 |
9 | #import "MDSwipeInteractionController.h"
10 |
11 | @interface MDVerticalSwipInteractionController : MDSwipeInteractionController
12 |
13 | // The vertical offset is top edge of content view, default is 20.f.
14 | @property (nonatomic, assign) CGFloat verticalTranslation;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/MDTransitioning/MDVerticalSwipInteractionController.m:
--------------------------------------------------------------------------------
1 | //
2 | // MDVerticalSwipInteractionController.m
3 | // Demo
4 | //
5 | // Created by Jave on 2017/9/24.
6 | // Copyright © 2017年 markejave. All rights reserved.
7 | //
8 |
9 | #import "MDVerticalSwipInteractionController.h"
10 |
11 | @implementation MDVerticalSwipInteractionController
12 |
13 | - (instancetype)initWithViewController:(UIViewController *)viewController{
14 | if (self = [super initWithViewController:viewController]) {
15 | __block __weak MDVerticalSwipInteractionController *weak_self = self;
16 | self.verticalTranslation = 200.f;
17 | self.allowSwipe = ^CGFloat(CGPoint location, CGPoint velocity) {
18 | return velocity.y > 0;
19 | };
20 | self.progress = ^CGFloat(CGPoint location, CGPoint translation, CGPoint velocity) {
21 | return translation.y / weak_self.verticalTranslation;
22 | };
23 | }
24 | return self;
25 | }
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/MDTransitioning/MDVerticalSwipPopInteractionController.h:
--------------------------------------------------------------------------------
1 | //
2 | // MDVerticalSwipPopInteractionController.h
3 | // MDTransitioning
4 | //
5 | // Created by xulinfeng on 2018/4/11.
6 | // Copyright © 2018年 markejave. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface MDVerticalSwipPopInteractionController : MDVerticalSwipInteractionController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/MDTransitioning/MDVerticalSwipPopInteractionController.m:
--------------------------------------------------------------------------------
1 | //
2 | // MDVerticalSwipPopInteractionController.m
3 | // MDTransitioning
4 | //
5 | // Created by xulinfeng on 2018/4/11.
6 | // Copyright © 2018年 markejave. All rights reserved.
7 | //
8 |
9 | #import "MDVerticalSwipPopInteractionController.h"
10 |
11 | @implementation MDVerticalSwipPopInteractionController
12 |
13 | - (instancetype)initWithViewController:(UIViewController *)viewController{
14 | if (self = [super initWithViewController:viewController]) {
15 | self.begin = ^(id interactiveTransition){
16 | [[viewController navigationController] popViewControllerAnimated:YES];
17 | };
18 | }
19 | return self;
20 | }
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/MDTransitioning/UIViewController+MDNavigationTransitioning.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import "MDInteractionController.h"
22 |
23 | // The default implementation of MDNavigationPopController.
24 | @interface UIViewController (MDNavigationTransitioning)
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/MDTransitioning/UIViewController+MDNavigationTransitioning.m:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import "UIViewController+MDNavigationTransitioning.h"
22 | #import "MDTransitioning+Private.h"
23 | #import "MDPopInteractionController.h"
24 | #import "MDNavigationAnimationController.h"
25 |
26 | MDTransitioningLoadCategory(UIViewController_MDNavigationTransitioning)
27 |
28 | @implementation UINavigationController (MDNavigationTransitioning)
29 |
30 | + (void)load {
31 | static dispatch_once_t onceToken;
32 | dispatch_once(&onceToken, ^{
33 | MDTransitioningMethodSwizzle([self class], @selector(pushViewController:animated:), @selector(MDNavigationTransitioning_pushViewController:animated:));
34 | });
35 | }
36 |
37 | - (void)MDNavigationTransitioning_pushViewController:(UIViewController *)viewController animated:(BOOL)animated{
38 | UIViewController *topViewController = (UIViewController *)[self topViewController];
39 | if (topViewController.tabBarController) {
40 | topViewController.snapshot = [topViewController.tabBarController.view snapshotViewAfterScreenUpdates:NO];
41 | } else {
42 | topViewController.snapshot = [self.view snapshotViewAfterScreenUpdates:NO];
43 | }
44 | if (!self.navigationBarHidden) topViewController.navigationBarSnapshot = [self.navigationBar snapshotViewAfterScreenUpdates:NO];
45 |
46 | [self MDNavigationTransitioning_pushViewController:viewController animated:animated];
47 | }
48 |
49 | @end
50 |
51 | @implementation UIViewController (MDNavigationTransitioning)
52 |
53 | + (void)load {
54 | static dispatch_once_t onceToken;
55 | dispatch_once(&onceToken, ^{
56 | MDTransitioningMethodSwizzle([self class], @selector(viewDidLoad), @selector(MDNavigationTransitioning_viewDidLoad));
57 | MDTransitioningMethodSwizzle([self class], @selector(viewWillDisappear:), @selector(MDNavigationTransitioning_viewWillDisappear:));
58 | });
59 | }
60 |
61 | - (void)MDNavigationTransitioning_viewDidLoad{
62 | [self MDNavigationTransitioning_viewDidLoad];
63 |
64 | if ([self allowPopInteractive] &&
65 | ![self allowCustomPopInteractive] &&
66 | [self navigationController] != nil &&
67 | [[self navigationController] delegate] != nil &&
68 | [self navigationController] == [self parentViewController] &&
69 | [[[self navigationController] viewControllers] firstObject] != self) {
70 |
71 | self.interactionController = [self requirePopInteractionController];
72 | }
73 | }
74 |
75 | - (void)MDNavigationTransitioning_viewWillDisappear:(BOOL)animated {
76 | [self MDNavigationTransitioning_viewWillDisappear:animated];
77 | // Being popped, take a snapshot
78 | if ([self isMovingFromParentViewController]) {
79 | self.snapshot = [[[self navigationController] view] snapshotViewAfterScreenUpdates:NO];
80 |
81 | if (!self.navigationController.navigationBarHidden) {
82 | self.navigationBarSnapshot = [[[self navigationController] navigationBar] snapshotViewAfterScreenUpdates:NO];
83 | }
84 | }
85 | }
86 |
87 | - (UIView *)snapshot{
88 | return objc_getAssociatedObject(self, @selector(snapshot));
89 | }
90 |
91 | - (void)setSnapshot:(UIView *)snapshot{
92 | if (self.snapshot != snapshot) {
93 | objc_setAssociatedObject(self, @selector(snapshot), snapshot, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
94 | }
95 | }
96 |
97 | - (UIView *)navigationBarSnapshot{
98 | return objc_getAssociatedObject(self, @selector(navigationBarSnapshot));
99 | }
100 |
101 | - (void)setNavigationBarSnapshot:(UIView *)navigationBarSnapshot{
102 | if (self.navigationBarSnapshot != navigationBarSnapshot) {
103 | objc_setAssociatedObject(self, @selector(navigationBarSnapshot), navigationBarSnapshot, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
104 | }
105 | }
106 |
107 | - (void)setAllowPopInteractive:(BOOL)allowPopInteractive{
108 | objc_setAssociatedObject(self, @selector(allowPopInteractive), @(allowPopInteractive), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
109 | }
110 |
111 | - (BOOL)allowPopInteractive{
112 | id allowPopInteractiveAssociatedObject = objc_getAssociatedObject(self, @selector(allowPopInteractive));
113 | if (!allowPopInteractiveAssociatedObject) {
114 | allowPopInteractiveAssociatedObject = @YES;
115 | self.allowPopInteractive = YES;
116 | }
117 | return [allowPopInteractiveAssociatedObject boolValue];
118 | }
119 |
120 | - (void)setAllowCustomPopInteractive:(BOOL)allowCustomPopInteractive{
121 | objc_setAssociatedObject(self, @selector(allowCustomPopInteractive), @(allowCustomPopInteractive), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
122 | }
123 |
124 | - (BOOL)allowCustomPopInteractive{
125 | return [objc_getAssociatedObject(self, @selector(allowCustomPopInteractive)) boolValue];
126 | }
127 |
128 | - (id)interactionController{
129 | return objc_getAssociatedObject(self, @selector(interactionController));
130 | }
131 |
132 | - (void)setInteractionController:(id)interactionController{
133 | if ([self interactionController] != interactionController) {
134 | objc_setAssociatedObject(self, @selector(interactionController), interactionController, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
135 | }
136 | }
137 |
138 | - (id)requirePopInteractionController;{
139 | return [MDPopInteractionController interactionControllerWithViewController:self];
140 | }
141 |
142 | - (id)animationForNavigationOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController;{
143 | return [[MDNavigationAnimationController alloc] initWithNavigationControllerOperation:operation fromViewController:fromViewController toViewController:toViewController];
144 | }
145 |
146 | @end
147 |
--------------------------------------------------------------------------------
/MDTransitioning/UIViewController+MDPresentionTransitioning.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import "MDInteractionController.h"
22 |
23 | // The default implementation of MDPresentionController.
24 | @interface UIViewController (MDPresentionTransitioning)
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/MDTransitioning/UIViewController+MDPresentionTransitioning.m:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 Modool. All rights reserved.
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy
4 | // of this software and associated documentation files (the "Software"), to deal
5 | // in the Software without restriction, including without limitation the rights
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | // copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 |
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | #import
22 | #import "UIViewController+MDPresentionTransitioning.h"
23 | #import "MDTransitioning+Private.h"
24 | #import "MDPresentionAnimationController.h"
25 |
26 | MDTransitioningLoadCategory(UIViewController_MDPresentionTransitioning)
27 |
28 | @implementation UIViewController (MDPresentionTransitioning)
29 |
30 | - (void)setPresentionInteractionController:(id)presentionInteractionController{
31 | objc_setAssociatedObject(self, @selector(presentionInteractionController), presentionInteractionController, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
32 | }
33 |
34 | - (id)presentionInteractionController{
35 | return objc_getAssociatedObject(self, @selector(presentionInteractionController));
36 | }
37 |
38 | - (id)animationForPresentionOperation:(MDPresentionAnimatedOperation)operation fromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController;{
39 | return [[MDPresentionAnimationController alloc] initWithPresentionAnimatedOperation:operation fromViewController:fromViewController toViewController:toViewController];
40 | }
41 |
42 | @end
43 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MDTransitioning
2 |
3 | [](https://github.com/Modool)
4 | [](https://developer.apple.com/Objective-C)
5 | [](https://developer.apple.com/iphone/index.action)
6 | [](https://github.com/Modool)
7 | [](http://wpa.qq.com/msgrd?v=3&uin=662988771&site=qq&menu=yes)
8 |
9 | ## Introduction
10 |
11 | - Animation based with transtion, easy to custom gesture control by developer.
12 | - Quick Integrate global gesture, sideslip or local animation
13 |
14 | ## How To Get Started
15 |
16 | * Download `MDTransitioning` and try run example app
17 |
18 | ## Installation
19 |
20 |
21 | * Installation with CocoaPods
22 |
23 | ```
24 | source 'https://github.com/Modool/cocoapods-specs.git'
25 | platform :ios, '8.0'
26 |
27 | target 'TargetName' do
28 | pod 'MDTransitioning', '~> 1.0.2'
29 | end
30 |
31 | ```
32 |
33 | * Installation with Carthage
34 |
35 | ```
36 | github "Modool/MDTransitioning" ~> 1.0.2
37 | ```
38 |
39 | * Manual Import
40 |
41 | ```
42 | drag “MDTransitioning” directory into your project
43 |
44 | ```
45 |
46 |
47 | ## Requirements
48 | - Requires ARC
49 |
50 | ## Architecture
51 |
52 | ### AnimatedTransitioning
53 |
54 | * ``
55 | * ``
56 | * ``
57 | * ``
58 | * `MDNavigationAnimationController`
59 | * `MDPresentionAnimationController`
60 |
61 | ### InteractiveController
62 |
63 | * ``
64 | * ``
65 | * ``
66 | * `MDSwipeInteractionController`
67 | * `MDPopInteractionController`
68 | * `UIViewController+MDNavigationTransitioning`
69 | * `UIViewController+MDPresentionTransitioning`
70 |
71 | ### ImageViewController
72 |
73 | * `AnimatedTransitioning`
74 | * `MDImageZoomAnimationController`
75 | * `InteractiveTransition`
76 | * `MDImageDismissInteractionController`
77 | * `MDImageDraggingDismissInteractionController`
78 | * `MDImageViewController`
79 |
80 | ## Usage
81 |
82 | * Demo FYI
83 |
84 | ## Update History
85 |
86 | * 2017.7.30 Add README and adjust project class name.
87 |
88 | ## License
89 | `MDTransitioning` is released under the MIT license. See LICENSE for details.
90 |
91 | ## Article
92 |
93 | Article support if you want to see more extension or demo. Go.
94 |
95 | ## Communication
96 |
97 | 

98 |
--------------------------------------------------------------------------------
/snapshots/custom_present.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Modool/MDTransitioning/d2f6ee1b9cbcc4e59d2108d27612cad540198542/snapshots/custom_present.gif
--------------------------------------------------------------------------------
/snapshots/custom_push.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Modool/MDTransitioning/d2f6ee1b9cbcc4e59d2108d27612cad540198542/snapshots/custom_push.gif
--------------------------------------------------------------------------------
/snapshots/image_present.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Modool/MDTransitioning/d2f6ee1b9cbcc4e59d2108d27612cad540198542/snapshots/image_present.gif
--------------------------------------------------------------------------------
/snapshots/scale_push.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Modool/MDTransitioning/d2f6ee1b9cbcc4e59d2108d27612cad540198542/snapshots/scale_push.gif
--------------------------------------------------------------------------------
/snapshots/system_present.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Modool/MDTransitioning/d2f6ee1b9cbcc4e59d2108d27612cad540198542/snapshots/system_present.gif
--------------------------------------------------------------------------------
/snapshots/system_push.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Modool/MDTransitioning/d2f6ee1b9cbcc4e59d2108d27612cad540198542/snapshots/system_push.gif
--------------------------------------------------------------------------------
/snapshots/vertical_pop.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Modool/MDTransitioning/d2f6ee1b9cbcc4e59d2108d27612cad540198542/snapshots/vertical_pop.gif
--------------------------------------------------------------------------------