├── .gitignore ├── LICENSE ├── README.md ├── VPInteractiveImageView.podspec └── VPInteractiveImageViewController ├── VPInteractiveImageViewController.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── VPInteractiveImageViewController ├── Example │ ├── VPAppDelegate.h │ ├── VPAppDelegate.m │ ├── VPExampleCell.h │ ├── VPExampleCell.m │ ├── VPExampleViewController.h │ └── VPExampleViewController.m ├── Images.xcassets │ ├── 0.imageset │ │ ├── 0.png │ │ └── Contents.json │ ├── 1.imageset │ │ ├── 1.png │ │ └── Contents.json │ ├── 2.imageset │ │ ├── 2.png │ │ └── Contents.json │ ├── 3.imageset │ │ ├── 3.png │ │ └── Contents.json │ ├── 4.imageset │ │ ├── 4.png │ │ └── Contents.json │ ├── 5.imageset │ │ ├── 5.png │ │ └── Contents.json │ ├── 6.imageset │ │ ├── 6.png │ │ └── Contents.json │ ├── 7.imageset │ │ ├── 7.png │ │ └── Contents.json │ ├── 8.imageset │ │ ├── 8.png │ │ └── Contents.json │ ├── 9.imageset │ │ ├── 9.png │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── LaunchImage.launchimage │ │ └── Contents.json ├── VPInteractiveImageView.h ├── VPInteractiveImageView.m ├── VPInteractiveImageViewController-Info.plist ├── VPInteractiveImageViewController-Prefix.pch ├── VPInteractiveImageViewController.h ├── VPInteractiveImageViewController.m ├── VPTransitionAnimator.h ├── VPTransitionAnimator.m ├── VPTransitionDelegate.h ├── VPTransitionDelegate.m ├── VPTransitionInteractor.h ├── VPTransitionInteractor.m ├── en.lproj │ └── InfoPlist.strings └── main.m └── VPInteractiveImageViewControllerTests ├── VPInteractiveImageViewControllerTests-Info.plist ├── VPInteractiveImageViewControllerTests.m └── en.lproj └── InfoPlist.strings /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | */build/* 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | profile 14 | *.moved-aside 15 | DerivedData 16 | .idea/ 17 | *.hmap 18 | *.xccheckout 19 | 20 | #CocoaPods 21 | Pods 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Vidu Pirathaparajah 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | VPInteractiveImageViewController 2 | ================================ 3 | 4 | An ImageViewController which presents Images Fullscreen and can be interactively dismissed as seen in the Facebook app 5 | 6 | Getting started 7 | --------------- 8 | 9 | ### Install using CocoaPods 10 | 11 | pod 'VPInteractiveImageView', '~> 0.2.0' 12 | 13 | ### Usage 14 | 15 | Add the import to your View Controller 16 | 17 | #import 18 | 19 | Present your interactive image in fullscreen 20 | 21 | - (void)presentInteractiveImage { 22 | VPInteractiveImageView *interactiveImageView = [[VPInteractiveImageView alloc] initWithImage:myImageView.image]; 23 | [interactiveImageView presentFullscreen]; 24 | } -------------------------------------------------------------------------------- /VPInteractiveImageView.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "VPInteractiveImageView" 3 | s.version = "0.4.0-beta" 4 | s.platform = :ios, '8.0' 5 | s.summary = "VPInteractiveImageView is a gesture based (Fullscreen) image display component as seen in iOS 7 Photos app or Facebook Paper" 6 | s.homepage = "https://github.com/vimacs/VPInteractiveImageViewController" 7 | s.license = { :type => 'MIT', :file => 'LICENSE' } 8 | s.author = { "Vidu Pirathaparajah" => "writetovidu@gmail.com" } 9 | s.source = { :git => "#{s.homepage}.git", :tag => "#{s.version}" } 10 | s.source_files = 'VPInteractiveImageViewController', 'VPInteractiveImageViewController/VPInteractiveImageViewController/VP*.{h,m}' 11 | s.requires_arc = true 12 | end 13 | 14 | -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 122B94B5189711D900D1D078 /* VPInteractiveImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 122B94B4189711D900D1D078 /* VPInteractiveImageView.m */; }; 11 | 122B94B8189717C700D1D078 /* VPInteractiveImageViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 122B94B7189717C700D1D078 /* VPInteractiveImageViewController.m */; }; 12 | 12375E6A1896FFD300279949 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12375E691896FFD300279949 /* Foundation.framework */; }; 13 | 12375E6C1896FFD300279949 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12375E6B1896FFD300279949 /* CoreGraphics.framework */; }; 14 | 12375E6E1896FFD300279949 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12375E6D1896FFD300279949 /* UIKit.framework */; }; 15 | 12375E741896FFD300279949 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 12375E721896FFD300279949 /* InfoPlist.strings */; }; 16 | 12375E761896FFD300279949 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 12375E751896FFD300279949 /* main.m */; }; 17 | 12375E7C1896FFD300279949 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 12375E7B1896FFD300279949 /* Images.xcassets */; }; 18 | 12375E831896FFD300279949 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12375E821896FFD300279949 /* XCTest.framework */; }; 19 | 12375E841896FFD300279949 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12375E691896FFD300279949 /* Foundation.framework */; }; 20 | 12375E851896FFD300279949 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12375E6D1896FFD300279949 /* UIKit.framework */; }; 21 | 12375E8D1896FFD400279949 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 12375E8B1896FFD300279949 /* InfoPlist.strings */; }; 22 | 12375E8F1896FFD400279949 /* VPInteractiveImageViewControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 12375E8E1896FFD400279949 /* VPInteractiveImageViewControllerTests.m */; }; 23 | 12F4B8B318B1192A005CD20D /* VPTransitionInteractor.m in Sources */ = {isa = PBXBuildFile; fileRef = 12F4B8B218B1192A005CD20D /* VPTransitionInteractor.m */; }; 24 | 12F4B8BB18B24EF9005CD20D /* VPAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 12F4B8B618B24EF9005CD20D /* VPAppDelegate.m */; }; 25 | 12F4B8BC18B24EF9005CD20D /* VPExampleCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 12F4B8B818B24EF9005CD20D /* VPExampleCell.m */; }; 26 | 12F4B8BD18B24EF9005CD20D /* VPExampleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 12F4B8BA18B24EF9005CD20D /* VPExampleViewController.m */; }; 27 | 12F947F2189D95F40082CC71 /* VPTransitionDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 12F947F1189D95F40082CC71 /* VPTransitionDelegate.m */; }; 28 | 12F947F3189D95F40082CC71 /* VPTransitionDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 12F947F1189D95F40082CC71 /* VPTransitionDelegate.m */; }; 29 | 12F947F6189D982B0082CC71 /* VPTransitionAnimator.m in Sources */ = {isa = PBXBuildFile; fileRef = 12F947F5189D982B0082CC71 /* VPTransitionAnimator.m */; }; 30 | 12F947F7189D982B0082CC71 /* VPTransitionAnimator.m in Sources */ = {isa = PBXBuildFile; fileRef = 12F947F5189D982B0082CC71 /* VPTransitionAnimator.m */; }; 31 | /* End PBXBuildFile section */ 32 | 33 | /* Begin PBXContainerItemProxy section */ 34 | 12375E861896FFD300279949 /* PBXContainerItemProxy */ = { 35 | isa = PBXContainerItemProxy; 36 | containerPortal = 12375E5E1896FFD300279949 /* Project object */; 37 | proxyType = 1; 38 | remoteGlobalIDString = 12375E651896FFD300279949; 39 | remoteInfo = VPInteractiveImageViewController; 40 | }; 41 | /* End PBXContainerItemProxy section */ 42 | 43 | /* Begin PBXFileReference section */ 44 | 122B94B3189711D900D1D078 /* VPInteractiveImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VPInteractiveImageView.h; sourceTree = ""; }; 45 | 122B94B4189711D900D1D078 /* VPInteractiveImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VPInteractiveImageView.m; sourceTree = ""; }; 46 | 122B94B6189717C700D1D078 /* VPInteractiveImageViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VPInteractiveImageViewController.h; sourceTree = ""; }; 47 | 122B94B7189717C700D1D078 /* VPInteractiveImageViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VPInteractiveImageViewController.m; sourceTree = ""; }; 48 | 12375E661896FFD300279949 /* VPInteractiveImageViewController.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = VPInteractiveImageViewController.app; sourceTree = BUILT_PRODUCTS_DIR; }; 49 | 12375E691896FFD300279949 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 50 | 12375E6B1896FFD300279949 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 51 | 12375E6D1896FFD300279949 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 52 | 12375E711896FFD300279949 /* VPInteractiveImageViewController-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "VPInteractiveImageViewController-Info.plist"; sourceTree = ""; }; 53 | 12375E731896FFD300279949 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 54 | 12375E751896FFD300279949 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 55 | 12375E771896FFD300279949 /* VPInteractiveImageViewController-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "VPInteractiveImageViewController-Prefix.pch"; sourceTree = ""; }; 56 | 12375E7B1896FFD300279949 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 57 | 12375E811896FFD300279949 /* VPInteractiveImageViewControllerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = VPInteractiveImageViewControllerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 58 | 12375E821896FFD300279949 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 59 | 12375E8A1896FFD300279949 /* VPInteractiveImageViewControllerTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "VPInteractiveImageViewControllerTests-Info.plist"; sourceTree = ""; }; 60 | 12375E8C1896FFD400279949 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 61 | 12375E8E1896FFD400279949 /* VPInteractiveImageViewControllerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VPInteractiveImageViewControllerTests.m; sourceTree = ""; }; 62 | 12F4B8B118B1192A005CD20D /* VPTransitionInteractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VPTransitionInteractor.h; sourceTree = ""; }; 63 | 12F4B8B218B1192A005CD20D /* VPTransitionInteractor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VPTransitionInteractor.m; sourceTree = ""; }; 64 | 12F4B8B518B24EF9005CD20D /* VPAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VPAppDelegate.h; path = Example/VPAppDelegate.h; sourceTree = ""; }; 65 | 12F4B8B618B24EF9005CD20D /* VPAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VPAppDelegate.m; path = Example/VPAppDelegate.m; sourceTree = ""; }; 66 | 12F4B8B718B24EF9005CD20D /* VPExampleCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VPExampleCell.h; path = Example/VPExampleCell.h; sourceTree = ""; }; 67 | 12F4B8B818B24EF9005CD20D /* VPExampleCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VPExampleCell.m; path = Example/VPExampleCell.m; sourceTree = ""; }; 68 | 12F4B8B918B24EF9005CD20D /* VPExampleViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VPExampleViewController.h; path = Example/VPExampleViewController.h; sourceTree = ""; }; 69 | 12F4B8BA18B24EF9005CD20D /* VPExampleViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VPExampleViewController.m; path = Example/VPExampleViewController.m; sourceTree = ""; }; 70 | 12F947F0189D95F40082CC71 /* VPTransitionDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VPTransitionDelegate.h; sourceTree = ""; }; 71 | 12F947F1189D95F40082CC71 /* VPTransitionDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VPTransitionDelegate.m; sourceTree = ""; }; 72 | 12F947F4189D982B0082CC71 /* VPTransitionAnimator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VPTransitionAnimator.h; sourceTree = ""; }; 73 | 12F947F5189D982B0082CC71 /* VPTransitionAnimator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VPTransitionAnimator.m; sourceTree = ""; }; 74 | /* End PBXFileReference section */ 75 | 76 | /* Begin PBXFrameworksBuildPhase section */ 77 | 12375E631896FFD300279949 /* Frameworks */ = { 78 | isa = PBXFrameworksBuildPhase; 79 | buildActionMask = 2147483647; 80 | files = ( 81 | 12375E6C1896FFD300279949 /* CoreGraphics.framework in Frameworks */, 82 | 12375E6E1896FFD300279949 /* UIKit.framework in Frameworks */, 83 | 12375E6A1896FFD300279949 /* Foundation.framework in Frameworks */, 84 | ); 85 | runOnlyForDeploymentPostprocessing = 0; 86 | }; 87 | 12375E7E1896FFD300279949 /* Frameworks */ = { 88 | isa = PBXFrameworksBuildPhase; 89 | buildActionMask = 2147483647; 90 | files = ( 91 | 12375E831896FFD300279949 /* XCTest.framework in Frameworks */, 92 | 12375E851896FFD300279949 /* UIKit.framework in Frameworks */, 93 | 12375E841896FFD300279949 /* Foundation.framework in Frameworks */, 94 | ); 95 | runOnlyForDeploymentPostprocessing = 0; 96 | }; 97 | /* End PBXFrameworksBuildPhase section */ 98 | 99 | /* Begin PBXGroup section */ 100 | 12375E5D1896FFD300279949 = { 101 | isa = PBXGroup; 102 | children = ( 103 | 12375E6F1896FFD300279949 /* VPInteractiveImageViewController */, 104 | 12375E881896FFD300279949 /* VPInteractiveImageViewControllerTests */, 105 | 12375E681896FFD300279949 /* Frameworks */, 106 | 12375E671896FFD300279949 /* Products */, 107 | ); 108 | sourceTree = ""; 109 | }; 110 | 12375E671896FFD300279949 /* Products */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | 12375E661896FFD300279949 /* VPInteractiveImageViewController.app */, 114 | 12375E811896FFD300279949 /* VPInteractiveImageViewControllerTests.xctest */, 115 | ); 116 | name = Products; 117 | sourceTree = ""; 118 | }; 119 | 12375E681896FFD300279949 /* Frameworks */ = { 120 | isa = PBXGroup; 121 | children = ( 122 | 12375E691896FFD300279949 /* Foundation.framework */, 123 | 12375E6B1896FFD300279949 /* CoreGraphics.framework */, 124 | 12375E6D1896FFD300279949 /* UIKit.framework */, 125 | 12375E821896FFD300279949 /* XCTest.framework */, 126 | ); 127 | name = Frameworks; 128 | sourceTree = ""; 129 | }; 130 | 12375E6F1896FFD300279949 /* VPInteractiveImageViewController */ = { 131 | isa = PBXGroup; 132 | children = ( 133 | 122B94B3189711D900D1D078 /* VPInteractiveImageView.h */, 134 | 122B94B4189711D900D1D078 /* VPInteractiveImageView.m */, 135 | 12F4B8B418B24DEC005CD20D /* Supporting Files */, 136 | 12F4B8BE18B24F11005CD20D /* Example */, 137 | 12375E7B1896FFD300279949 /* Images.xcassets */, 138 | 12375E701896FFD300279949 /* Supporting Files */, 139 | ); 140 | path = VPInteractiveImageViewController; 141 | sourceTree = ""; 142 | }; 143 | 12375E701896FFD300279949 /* Supporting Files */ = { 144 | isa = PBXGroup; 145 | children = ( 146 | 12375E711896FFD300279949 /* VPInteractiveImageViewController-Info.plist */, 147 | 12375E721896FFD300279949 /* InfoPlist.strings */, 148 | 12375E751896FFD300279949 /* main.m */, 149 | 12375E771896FFD300279949 /* VPInteractiveImageViewController-Prefix.pch */, 150 | ); 151 | name = "Supporting Files"; 152 | sourceTree = ""; 153 | }; 154 | 12375E881896FFD300279949 /* VPInteractiveImageViewControllerTests */ = { 155 | isa = PBXGroup; 156 | children = ( 157 | 12375E8E1896FFD400279949 /* VPInteractiveImageViewControllerTests.m */, 158 | 12375E891896FFD300279949 /* Supporting Files */, 159 | ); 160 | path = VPInteractiveImageViewControllerTests; 161 | sourceTree = ""; 162 | }; 163 | 12375E891896FFD300279949 /* Supporting Files */ = { 164 | isa = PBXGroup; 165 | children = ( 166 | 12375E8A1896FFD300279949 /* VPInteractiveImageViewControllerTests-Info.plist */, 167 | 12375E8B1896FFD300279949 /* InfoPlist.strings */, 168 | ); 169 | name = "Supporting Files"; 170 | sourceTree = ""; 171 | }; 172 | 12F4B8B418B24DEC005CD20D /* Supporting Files */ = { 173 | isa = PBXGroup; 174 | children = ( 175 | 122B94B6189717C700D1D078 /* VPInteractiveImageViewController.h */, 176 | 122B94B7189717C700D1D078 /* VPInteractiveImageViewController.m */, 177 | 12F947F0189D95F40082CC71 /* VPTransitionDelegate.h */, 178 | 12F947F1189D95F40082CC71 /* VPTransitionDelegate.m */, 179 | 12F947F4189D982B0082CC71 /* VPTransitionAnimator.h */, 180 | 12F947F5189D982B0082CC71 /* VPTransitionAnimator.m */, 181 | 12F4B8B118B1192A005CD20D /* VPTransitionInteractor.h */, 182 | 12F4B8B218B1192A005CD20D /* VPTransitionInteractor.m */, 183 | ); 184 | name = "Supporting Files"; 185 | sourceTree = ""; 186 | }; 187 | 12F4B8BE18B24F11005CD20D /* Example */ = { 188 | isa = PBXGroup; 189 | children = ( 190 | 12F4B8B518B24EF9005CD20D /* VPAppDelegate.h */, 191 | 12F4B8B618B24EF9005CD20D /* VPAppDelegate.m */, 192 | 12F4B8B718B24EF9005CD20D /* VPExampleCell.h */, 193 | 12F4B8B818B24EF9005CD20D /* VPExampleCell.m */, 194 | 12F4B8B918B24EF9005CD20D /* VPExampleViewController.h */, 195 | 12F4B8BA18B24EF9005CD20D /* VPExampleViewController.m */, 196 | ); 197 | name = Example; 198 | sourceTree = ""; 199 | }; 200 | /* End PBXGroup section */ 201 | 202 | /* Begin PBXNativeTarget section */ 203 | 12375E651896FFD300279949 /* VPInteractiveImageViewController */ = { 204 | isa = PBXNativeTarget; 205 | buildConfigurationList = 12375E921896FFD400279949 /* Build configuration list for PBXNativeTarget "VPInteractiveImageViewController" */; 206 | buildPhases = ( 207 | 12375E621896FFD300279949 /* Sources */, 208 | 12375E631896FFD300279949 /* Frameworks */, 209 | 12375E641896FFD300279949 /* Resources */, 210 | ); 211 | buildRules = ( 212 | ); 213 | dependencies = ( 214 | ); 215 | name = VPInteractiveImageViewController; 216 | productName = VPInteractiveImageViewController; 217 | productReference = 12375E661896FFD300279949 /* VPInteractiveImageViewController.app */; 218 | productType = "com.apple.product-type.application"; 219 | }; 220 | 12375E801896FFD300279949 /* VPInteractiveImageViewControllerTests */ = { 221 | isa = PBXNativeTarget; 222 | buildConfigurationList = 12375E951896FFD400279949 /* Build configuration list for PBXNativeTarget "VPInteractiveImageViewControllerTests" */; 223 | buildPhases = ( 224 | 12375E7D1896FFD300279949 /* Sources */, 225 | 12375E7E1896FFD300279949 /* Frameworks */, 226 | 12375E7F1896FFD300279949 /* Resources */, 227 | ); 228 | buildRules = ( 229 | ); 230 | dependencies = ( 231 | 12375E871896FFD300279949 /* PBXTargetDependency */, 232 | ); 233 | name = VPInteractiveImageViewControllerTests; 234 | productName = VPInteractiveImageViewControllerTests; 235 | productReference = 12375E811896FFD300279949 /* VPInteractiveImageViewControllerTests.xctest */; 236 | productType = "com.apple.product-type.bundle.unit-test"; 237 | }; 238 | /* End PBXNativeTarget section */ 239 | 240 | /* Begin PBXProject section */ 241 | 12375E5E1896FFD300279949 /* Project object */ = { 242 | isa = PBXProject; 243 | attributes = { 244 | CLASSPREFIX = VP; 245 | LastUpgradeCheck = 0700; 246 | ORGANIZATIONNAME = "Vidu Pirathaparajah"; 247 | TargetAttributes = { 248 | 12375E801896FFD300279949 = { 249 | TestTargetID = 12375E651896FFD300279949; 250 | }; 251 | }; 252 | }; 253 | buildConfigurationList = 12375E611896FFD300279949 /* Build configuration list for PBXProject "VPInteractiveImageViewController" */; 254 | compatibilityVersion = "Xcode 3.2"; 255 | developmentRegion = English; 256 | hasScannedForEncodings = 0; 257 | knownRegions = ( 258 | en, 259 | ); 260 | mainGroup = 12375E5D1896FFD300279949; 261 | productRefGroup = 12375E671896FFD300279949 /* Products */; 262 | projectDirPath = ""; 263 | projectRoot = ""; 264 | targets = ( 265 | 12375E651896FFD300279949 /* VPInteractiveImageViewController */, 266 | 12375E801896FFD300279949 /* VPInteractiveImageViewControllerTests */, 267 | ); 268 | }; 269 | /* End PBXProject section */ 270 | 271 | /* Begin PBXResourcesBuildPhase section */ 272 | 12375E641896FFD300279949 /* Resources */ = { 273 | isa = PBXResourcesBuildPhase; 274 | buildActionMask = 2147483647; 275 | files = ( 276 | 12375E741896FFD300279949 /* InfoPlist.strings in Resources */, 277 | 12375E7C1896FFD300279949 /* Images.xcassets in Resources */, 278 | ); 279 | runOnlyForDeploymentPostprocessing = 0; 280 | }; 281 | 12375E7F1896FFD300279949 /* Resources */ = { 282 | isa = PBXResourcesBuildPhase; 283 | buildActionMask = 2147483647; 284 | files = ( 285 | 12375E8D1896FFD400279949 /* InfoPlist.strings in Resources */, 286 | ); 287 | runOnlyForDeploymentPostprocessing = 0; 288 | }; 289 | /* End PBXResourcesBuildPhase section */ 290 | 291 | /* Begin PBXSourcesBuildPhase section */ 292 | 12375E621896FFD300279949 /* Sources */ = { 293 | isa = PBXSourcesBuildPhase; 294 | buildActionMask = 2147483647; 295 | files = ( 296 | 122B94B5189711D900D1D078 /* VPInteractiveImageView.m in Sources */, 297 | 12F947F2189D95F40082CC71 /* VPTransitionDelegate.m in Sources */, 298 | 12F4B8BB18B24EF9005CD20D /* VPAppDelegate.m in Sources */, 299 | 12F4B8B318B1192A005CD20D /* VPTransitionInteractor.m in Sources */, 300 | 12F4B8BD18B24EF9005CD20D /* VPExampleViewController.m in Sources */, 301 | 12F4B8BC18B24EF9005CD20D /* VPExampleCell.m in Sources */, 302 | 12F947F6189D982B0082CC71 /* VPTransitionAnimator.m in Sources */, 303 | 12375E761896FFD300279949 /* main.m in Sources */, 304 | 122B94B8189717C700D1D078 /* VPInteractiveImageViewController.m in Sources */, 305 | ); 306 | runOnlyForDeploymentPostprocessing = 0; 307 | }; 308 | 12375E7D1896FFD300279949 /* Sources */ = { 309 | isa = PBXSourcesBuildPhase; 310 | buildActionMask = 2147483647; 311 | files = ( 312 | 12375E8F1896FFD400279949 /* VPInteractiveImageViewControllerTests.m in Sources */, 313 | 12F947F7189D982B0082CC71 /* VPTransitionAnimator.m in Sources */, 314 | 12F947F3189D95F40082CC71 /* VPTransitionDelegate.m in Sources */, 315 | ); 316 | runOnlyForDeploymentPostprocessing = 0; 317 | }; 318 | /* End PBXSourcesBuildPhase section */ 319 | 320 | /* Begin PBXTargetDependency section */ 321 | 12375E871896FFD300279949 /* PBXTargetDependency */ = { 322 | isa = PBXTargetDependency; 323 | target = 12375E651896FFD300279949 /* VPInteractiveImageViewController */; 324 | targetProxy = 12375E861896FFD300279949 /* PBXContainerItemProxy */; 325 | }; 326 | /* End PBXTargetDependency section */ 327 | 328 | /* Begin PBXVariantGroup section */ 329 | 12375E721896FFD300279949 /* InfoPlist.strings */ = { 330 | isa = PBXVariantGroup; 331 | children = ( 332 | 12375E731896FFD300279949 /* en */, 333 | ); 334 | name = InfoPlist.strings; 335 | sourceTree = ""; 336 | }; 337 | 12375E8B1896FFD300279949 /* InfoPlist.strings */ = { 338 | isa = PBXVariantGroup; 339 | children = ( 340 | 12375E8C1896FFD400279949 /* en */, 341 | ); 342 | name = InfoPlist.strings; 343 | sourceTree = ""; 344 | }; 345 | /* End PBXVariantGroup section */ 346 | 347 | /* Begin XCBuildConfiguration section */ 348 | 12375E901896FFD400279949 /* Debug */ = { 349 | isa = XCBuildConfiguration; 350 | buildSettings = { 351 | ALWAYS_SEARCH_USER_PATHS = NO; 352 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 353 | CLANG_CXX_LIBRARY = "libc++"; 354 | CLANG_ENABLE_MODULES = YES; 355 | CLANG_ENABLE_OBJC_ARC = YES; 356 | CLANG_WARN_BOOL_CONVERSION = YES; 357 | CLANG_WARN_CONSTANT_CONVERSION = YES; 358 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 359 | CLANG_WARN_EMPTY_BODY = YES; 360 | CLANG_WARN_ENUM_CONVERSION = YES; 361 | CLANG_WARN_INT_CONVERSION = YES; 362 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 363 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 364 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 365 | COPY_PHASE_STRIP = NO; 366 | ENABLE_TESTABILITY = YES; 367 | GCC_C_LANGUAGE_STANDARD = gnu99; 368 | GCC_DYNAMIC_NO_PIC = NO; 369 | GCC_OPTIMIZATION_LEVEL = 0; 370 | GCC_PREPROCESSOR_DEFINITIONS = ( 371 | "DEBUG=1", 372 | "$(inherited)", 373 | ); 374 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 375 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 376 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 377 | GCC_WARN_UNDECLARED_SELECTOR = YES; 378 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 379 | GCC_WARN_UNUSED_FUNCTION = YES; 380 | GCC_WARN_UNUSED_VARIABLE = YES; 381 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 382 | ONLY_ACTIVE_ARCH = YES; 383 | SDKROOT = iphoneos; 384 | TARGETED_DEVICE_FAMILY = "1,2"; 385 | }; 386 | name = Debug; 387 | }; 388 | 12375E911896FFD400279949 /* Release */ = { 389 | isa = XCBuildConfiguration; 390 | buildSettings = { 391 | ALWAYS_SEARCH_USER_PATHS = NO; 392 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 393 | CLANG_CXX_LIBRARY = "libc++"; 394 | CLANG_ENABLE_MODULES = YES; 395 | CLANG_ENABLE_OBJC_ARC = YES; 396 | CLANG_WARN_BOOL_CONVERSION = YES; 397 | CLANG_WARN_CONSTANT_CONVERSION = YES; 398 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 399 | CLANG_WARN_EMPTY_BODY = YES; 400 | CLANG_WARN_ENUM_CONVERSION = YES; 401 | CLANG_WARN_INT_CONVERSION = YES; 402 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 403 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 404 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 405 | COPY_PHASE_STRIP = YES; 406 | ENABLE_NS_ASSERTIONS = NO; 407 | GCC_C_LANGUAGE_STANDARD = gnu99; 408 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 409 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 410 | GCC_WARN_UNDECLARED_SELECTOR = YES; 411 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 412 | GCC_WARN_UNUSED_FUNCTION = YES; 413 | GCC_WARN_UNUSED_VARIABLE = YES; 414 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 415 | SDKROOT = iphoneos; 416 | TARGETED_DEVICE_FAMILY = "1,2"; 417 | VALIDATE_PRODUCT = YES; 418 | }; 419 | name = Release; 420 | }; 421 | 12375E931896FFD400279949 /* Debug */ = { 422 | isa = XCBuildConfiguration; 423 | buildSettings = { 424 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 425 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 426 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 427 | GCC_PREFIX_HEADER = "VPInteractiveImageViewController/VPInteractiveImageViewController-Prefix.pch"; 428 | INFOPLIST_FILE = "VPInteractiveImageViewController/VPInteractiveImageViewController-Info.plist"; 429 | IPHONEOS_DEPLOYMENT_TARGET = 7.1; 430 | PRODUCT_BUNDLE_IDENTIFIER = "com.vidup.${PRODUCT_NAME:rfc1034identifier}"; 431 | PRODUCT_NAME = "$(TARGET_NAME)"; 432 | WRAPPER_EXTENSION = app; 433 | }; 434 | name = Debug; 435 | }; 436 | 12375E941896FFD400279949 /* Release */ = { 437 | isa = XCBuildConfiguration; 438 | buildSettings = { 439 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 440 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 441 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 442 | GCC_PREFIX_HEADER = "VPInteractiveImageViewController/VPInteractiveImageViewController-Prefix.pch"; 443 | INFOPLIST_FILE = "VPInteractiveImageViewController/VPInteractiveImageViewController-Info.plist"; 444 | IPHONEOS_DEPLOYMENT_TARGET = 7.1; 445 | PRODUCT_BUNDLE_IDENTIFIER = "com.vidup.${PRODUCT_NAME:rfc1034identifier}"; 446 | PRODUCT_NAME = "$(TARGET_NAME)"; 447 | WRAPPER_EXTENSION = app; 448 | }; 449 | name = Release; 450 | }; 451 | 12375E961896FFD400279949 /* Debug */ = { 452 | isa = XCBuildConfiguration; 453 | buildSettings = { 454 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/VPInteractiveImageViewController.app/VPInteractiveImageViewController"; 455 | FRAMEWORK_SEARCH_PATHS = ( 456 | "$(SDKROOT)/Developer/Library/Frameworks", 457 | "$(inherited)", 458 | "$(DEVELOPER_FRAMEWORKS_DIR)", 459 | ); 460 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 461 | GCC_PREFIX_HEADER = "VPInteractiveImageViewController/VPInteractiveImageViewController-Prefix.pch"; 462 | GCC_PREPROCESSOR_DEFINITIONS = ( 463 | "DEBUG=1", 464 | "$(inherited)", 465 | ); 466 | INFOPLIST_FILE = "VPInteractiveImageViewControllerTests/VPInteractiveImageViewControllerTests-Info.plist"; 467 | PRODUCT_BUNDLE_IDENTIFIER = "com.vidup.${PRODUCT_NAME:rfc1034identifier}"; 468 | PRODUCT_NAME = "$(TARGET_NAME)"; 469 | TEST_HOST = "$(BUNDLE_LOADER)"; 470 | WRAPPER_EXTENSION = xctest; 471 | }; 472 | name = Debug; 473 | }; 474 | 12375E971896FFD400279949 /* Release */ = { 475 | isa = XCBuildConfiguration; 476 | buildSettings = { 477 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/VPInteractiveImageViewController.app/VPInteractiveImageViewController"; 478 | FRAMEWORK_SEARCH_PATHS = ( 479 | "$(SDKROOT)/Developer/Library/Frameworks", 480 | "$(inherited)", 481 | "$(DEVELOPER_FRAMEWORKS_DIR)", 482 | ); 483 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 484 | GCC_PREFIX_HEADER = "VPInteractiveImageViewController/VPInteractiveImageViewController-Prefix.pch"; 485 | INFOPLIST_FILE = "VPInteractiveImageViewControllerTests/VPInteractiveImageViewControllerTests-Info.plist"; 486 | PRODUCT_BUNDLE_IDENTIFIER = "com.vidup.${PRODUCT_NAME:rfc1034identifier}"; 487 | PRODUCT_NAME = "$(TARGET_NAME)"; 488 | TEST_HOST = "$(BUNDLE_LOADER)"; 489 | WRAPPER_EXTENSION = xctest; 490 | }; 491 | name = Release; 492 | }; 493 | /* End XCBuildConfiguration section */ 494 | 495 | /* Begin XCConfigurationList section */ 496 | 12375E611896FFD300279949 /* Build configuration list for PBXProject "VPInteractiveImageViewController" */ = { 497 | isa = XCConfigurationList; 498 | buildConfigurations = ( 499 | 12375E901896FFD400279949 /* Debug */, 500 | 12375E911896FFD400279949 /* Release */, 501 | ); 502 | defaultConfigurationIsVisible = 0; 503 | defaultConfigurationName = Release; 504 | }; 505 | 12375E921896FFD400279949 /* Build configuration list for PBXNativeTarget "VPInteractiveImageViewController" */ = { 506 | isa = XCConfigurationList; 507 | buildConfigurations = ( 508 | 12375E931896FFD400279949 /* Debug */, 509 | 12375E941896FFD400279949 /* Release */, 510 | ); 511 | defaultConfigurationIsVisible = 0; 512 | defaultConfigurationName = Release; 513 | }; 514 | 12375E951896FFD400279949 /* Build configuration list for PBXNativeTarget "VPInteractiveImageViewControllerTests" */ = { 515 | isa = XCConfigurationList; 516 | buildConfigurations = ( 517 | 12375E961896FFD400279949 /* Debug */, 518 | 12375E971896FFD400279949 /* Release */, 519 | ); 520 | defaultConfigurationIsVisible = 0; 521 | defaultConfigurationName = Release; 522 | }; 523 | /* End XCConfigurationList section */ 524 | }; 525 | rootObject = 12375E5E1896FFD300279949 /* Project object */; 526 | } 527 | -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Example/VPAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // VPAppDelegate.h 3 | // VPInteractiveImageViewController 4 | // 5 | // Created by Vidu Pirathaparajah on 27/01/14. 6 | // Copyright (c) 2014 Vidu Pirathaparajah. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface VPAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Example/VPAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // VPAppDelegate.m 3 | // VPInteractiveImageViewController 4 | // 5 | // Created by Vidu Pirathaparajah on 27/01/14. 6 | // Copyright (c) 2014 Vidu Pirathaparajah. All rights reserved. 7 | // 8 | 9 | #import "VPAppDelegate.h" 10 | #import "VPExampleViewController.h" 11 | 12 | @implementation VPAppDelegate 13 | 14 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 15 | { 16 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 17 | // Override point for customization after application launch. 18 | self.window.backgroundColor = [UIColor whiteColor]; 19 | 20 | VPExampleViewController *rootViewController = [[VPExampleViewController alloc] init]; 21 | self.window.rootViewController = rootViewController; 22 | 23 | [self.window makeKeyAndVisible]; 24 | return YES; 25 | } 26 | 27 | - (void)applicationWillResignActive:(UIApplication *)application 28 | { 29 | // 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. 30 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 31 | } 32 | 33 | - (void)applicationDidEnterBackground:(UIApplication *)application 34 | { 35 | // 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. 36 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 37 | } 38 | 39 | - (void)applicationWillEnterForeground:(UIApplication *)application 40 | { 41 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 42 | } 43 | 44 | - (void)applicationDidBecomeActive:(UIApplication *)application 45 | { 46 | // 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. 47 | } 48 | 49 | - (void)applicationWillTerminate:(UIApplication *)application 50 | { 51 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 52 | } 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Example/VPExampleCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // VPExampleCell.h 3 | // VPInteractiveImageViewController 4 | // 5 | // Created by Vidu Pirathaparajah on 27/01/14. 6 | // Copyright (c) 2014 Vidu Pirathaparajah. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "VPInteractiveImageView.h" 11 | 12 | @interface VPExampleCell : UICollectionViewCell 13 | @property (nonatomic) VPInteractiveImageView *imageView; 14 | @end 15 | -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Example/VPExampleCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // VPExampleCell.m 3 | // VPInteractiveImageViewController 4 | // 5 | // Created by Vidu Pirathaparajah on 27/01/14. 6 | // Copyright (c) 2014 Vidu Pirathaparajah. All rights reserved. 7 | // 8 | 9 | #import "VPExampleCell.h" 10 | 11 | @interface VPExampleCell () 12 | 13 | @end 14 | 15 | @implementation VPExampleCell 16 | 17 | - (id)initWithFrame:(CGRect)frame 18 | { 19 | self = [super initWithFrame:frame]; 20 | if (self) { 21 | _imageView = [[VPInteractiveImageView alloc] initWithFrame:CGRectZero]; 22 | _imageView.pinchGestureEnabled = YES; 23 | _imageView.panCloseGestureEnabled = YES; 24 | [self.contentView addSubview:_imageView]; 25 | } 26 | return self; 27 | } 28 | 29 | - (void)layoutSubviews { 30 | [super layoutSubviews]; 31 | _imageView.frame = self.contentView.bounds; 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Example/VPExampleViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // VPExampleViewController.h 3 | // VPInteractiveImageViewController 4 | // 5 | // Created by Vidu Pirathaparajah on 27/01/14. 6 | // Copyright (c) 2014 Vidu Pirathaparajah. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface VPExampleViewController : UICollectionViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Example/VPExampleViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // VPExampleViewController.m 3 | // VPInteractiveImageViewController 4 | // 5 | // Created by Vidu Pirathaparajah on 27/01/14. 6 | // Copyright (c) 2014 Vidu Pirathaparajah. All rights reserved. 7 | // 8 | 9 | #import "VPExampleViewController.h" 10 | #import "VPExampleCell.h" 11 | 12 | #define CellID @"CellID" 13 | 14 | @interface VPExampleViewController () 15 | 16 | @end 17 | 18 | @implementation VPExampleViewController 19 | 20 | - (id)init { 21 | UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; 22 | layout.itemSize = CGSizeMake(300.0f, 200.0f); 23 | layout.minimumLineSpacing = 10.0f; 24 | layout.sectionInset = UIEdgeInsetsMake(0.0f, 5.0f, 0.0f, 5.0f); 25 | self = [super initWithCollectionViewLayout:layout];; 26 | if (self) { 27 | 28 | } 29 | return self; 30 | } 31 | 32 | - (void)viewDidLoad { 33 | [super viewDidLoad]; 34 | [self.collectionView registerClass:[VPExampleCell class] forCellWithReuseIdentifier:CellID]; 35 | self.collectionView.alwaysBounceVertical = YES; 36 | } 37 | 38 | - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { 39 | return 1; 40 | } 41 | 42 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { 43 | return 10; 44 | } 45 | 46 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 47 | VPExampleCell *cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:CellID 48 | forIndexPath:indexPath]; 49 | cell.imageView.delegate = self; 50 | NSString *imageName = [NSString stringWithFormat:@"%ld",(long)indexPath.row]; 51 | cell.imageView.image = [UIImage imageNamed:imageName]; 52 | return cell; 53 | } 54 | 55 | #pragma mark - VPInteractiveImageViewDelegate 56 | 57 | - (void)interactiveImageViewWillPresent:(VPInteractiveImageView *)imageView { 58 | NSLog(@"VPInteractiveImageView will present."); 59 | } 60 | 61 | - (void)interactiveImageViewWillDismiss:(VPInteractiveImageView *)imageView { 62 | NSLog(@"VPInteractiveImageView did dismiss."); 63 | } 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/0.imageset/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidugloeck/VPInteractiveImageViewController/b25fba65b7ff7e17e59c13e35f0e339f65526d20/VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/0.imageset/0.png -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/0.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "0.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/1.imageset/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidugloeck/VPInteractiveImageViewController/b25fba65b7ff7e17e59c13e35f0e339f65526d20/VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/1.imageset/1.png -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "1.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/2.imageset/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidugloeck/VPInteractiveImageViewController/b25fba65b7ff7e17e59c13e35f0e339f65526d20/VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/2.imageset/2.png -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "2.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/3.imageset/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidugloeck/VPInteractiveImageViewController/b25fba65b7ff7e17e59c13e35f0e339f65526d20/VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/3.imageset/3.png -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "3.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/4.imageset/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidugloeck/VPInteractiveImageViewController/b25fba65b7ff7e17e59c13e35f0e339f65526d20/VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/4.imageset/4.png -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "4.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/5.imageset/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidugloeck/VPInteractiveImageViewController/b25fba65b7ff7e17e59c13e35f0e339f65526d20/VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/5.imageset/5.png -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/5.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "5.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/6.imageset/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidugloeck/VPInteractiveImageViewController/b25fba65b7ff7e17e59c13e35f0e339f65526d20/VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/6.imageset/6.png -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/6.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "6.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/7.imageset/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidugloeck/VPInteractiveImageViewController/b25fba65b7ff7e17e59c13e35f0e339f65526d20/VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/7.imageset/7.png -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/7.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "7.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/8.imageset/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidugloeck/VPInteractiveImageViewController/b25fba65b7ff7e17e59c13e35f0e339f65526d20/VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/8.imageset/8.png -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/8.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "8.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/9.imageset/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidugloeck/VPInteractiveImageViewController/b25fba65b7ff7e17e59c13e35f0e339f65526d20/VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/9.imageset/9.png -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/9.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "9.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "ipad", 20 | "size" : "29x29", 21 | "scale" : "1x" 22 | }, 23 | { 24 | "idiom" : "ipad", 25 | "size" : "29x29", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "ipad", 30 | "size" : "40x40", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "40x40", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "76x76", 41 | "scale" : "1x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "76x76", 46 | "scale" : "2x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "orientation" : "portrait", 20 | "idiom" : "ipad", 21 | "extent" : "full-screen", 22 | "minimum-system-version" : "7.0", 23 | "scale" : "1x" 24 | }, 25 | { 26 | "orientation" : "landscape", 27 | "idiom" : "ipad", 28 | "extent" : "full-screen", 29 | "minimum-system-version" : "7.0", 30 | "scale" : "1x" 31 | }, 32 | { 33 | "orientation" : "portrait", 34 | "idiom" : "ipad", 35 | "extent" : "full-screen", 36 | "minimum-system-version" : "7.0", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "orientation" : "landscape", 41 | "idiom" : "ipad", 42 | "extent" : "full-screen", 43 | "minimum-system-version" : "7.0", 44 | "scale" : "2x" 45 | } 46 | ], 47 | "info" : { 48 | "version" : 1, 49 | "author" : "xcode" 50 | } 51 | } -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/VPInteractiveImageView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VPInteractiveImageView.h 3 | // VPInteractiveImageViewController 4 | // 5 | // Created by Vidu Pirathaparajah on 27/01/14. 6 | // Copyright (c) 2014 Vidu Pirathaparajah. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol VPInteractiveImageViewDelegate; 12 | 13 | @interface VPInteractiveImageView : UIImageView 14 | 15 | @property (nonatomic, weak) id delegate; 16 | @property (nonatomic) UIViewController *presentingViewController; 17 | @property (nonatomic) BOOL pinchGestureEnabled; 18 | @property (nonatomic) BOOL panCloseGestureEnabled; 19 | 20 | - (void)presentFullscreen; 21 | @end 22 | 23 | @protocol VPInteractiveImageViewDelegate 24 | 25 | @optional 26 | - (void)interactiveImageViewWillPresent:(VPInteractiveImageView *)imageView; 27 | - (void)interactiveImageViewWillDismiss:(VPInteractiveImageView *)imageView; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/VPInteractiveImageView.m: -------------------------------------------------------------------------------- 1 | // 2 | // VPInteractiveImageView.m 3 | // VPInteractiveImageViewController 4 | // 5 | // Created by Vidu Pirathaparajah on 27/01/14. 6 | // Copyright (c) 2014 Vidu Pirathaparajah. All rights reserved. 7 | // 8 | 9 | #import "VPInteractiveImageView.h" 10 | #import "VPInteractiveImageViewController.h" 11 | #import "VPTransitionDelegate.h" 12 | 13 | @interface VPInteractiveImageView () 14 | @property (nonatomic) VPTransitionDelegate *transitionDelegate; 15 | @end 16 | 17 | @implementation VPInteractiveImageView 18 | 19 | - (id)initWithFrame:(CGRect)frame 20 | { 21 | self = [super initWithFrame:frame]; 22 | if (self) { 23 | self.userInteractionEnabled = YES; 24 | UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self 25 | action:@selector(imageViewTapped:)]; 26 | [self addGestureRecognizer:recognizer]; 27 | _pinchGestureEnabled = YES; 28 | _panCloseGestureEnabled = YES; 29 | _transitionDelegate = [[VPTransitionDelegate alloc] initWithInteractiveImageView:self fullScreenImageView:nil]; 30 | _transitionDelegate.pinchGestureEnabled = _pinchGestureEnabled; 31 | _transitionDelegate.panCloseGestureEnabled = _panCloseGestureEnabled; 32 | } 33 | return self; 34 | } 35 | 36 | #pragma mark - Getter / Setter 37 | 38 | - (void)setPinchGestureEnabled:(BOOL)pinchGestureEnabled { 39 | _pinchGestureEnabled = pinchGestureEnabled; 40 | self.transitionDelegate.pinchGestureEnabled = pinchGestureEnabled; 41 | } 42 | 43 | - (void)setPanCloseGestureEnabled:(BOOL)panCloseGestureEnabled { 44 | _panCloseGestureEnabled = panCloseGestureEnabled; 45 | self.transitionDelegate.panCloseGestureEnabled = panCloseGestureEnabled; 46 | } 47 | 48 | - (void)imageViewTapped:(UITapGestureRecognizer *)recognizer { 49 | if ([self.delegate respondsToSelector:@selector(interactiveImageViewWillPresent:)]) { 50 | [self.delegate performSelector:@selector(interactiveImageViewWillPresent:) 51 | withObject:self]; 52 | } 53 | [self presentFullscreen]; 54 | } 55 | 56 | - (void)presentFullscreen { 57 | VPInteractiveImageViewController *controller = [[VPInteractiveImageViewController alloc] initWithInteractiveImageView:self]; 58 | controller.imageView.image = self.image; 59 | self.transitionDelegate.imageView = controller.imageView; 60 | controller.transitioningDelegate = self.transitionDelegate; 61 | if (self.presentingViewController) { 62 | [self.presentingViewController presentViewController:controller 63 | animated:YES 64 | completion:NULL]; 65 | } else { 66 | [UIApplication.sharedApplication.delegate.window.rootViewController presentViewController:controller 67 | animated:YES 68 | completion:NULL]; 69 | } 70 | } 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/VPInteractiveImageViewController-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 0.0.1 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 0.0.1 25 | LSRequiresIPhoneOS 26 | 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 | -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/VPInteractiveImageViewController-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_3_0 10 | #warning "This project uses features only available in iOS SDK 3.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/VPInteractiveImageViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // VPInteractiveImageViewController.h 3 | // VPInteractiveImageViewController 4 | // 5 | // Created by Vidu Pirathaparajah on 27/01/14. 6 | // Copyright (c) 2014 Vidu Pirathaparajah. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class VPInteractiveImageView; 12 | 13 | @interface VPInteractiveImageViewController : UIViewController 14 | @property (nonatomic, readonly) UIImageView *imageView; 15 | 16 | - (instancetype)initWithInteractiveImageView:(VPInteractiveImageView *)interactiveImageView NS_DESIGNATED_INITIALIZER; 17 | - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil NS_UNAVAILABLE; 18 | - (instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE; 19 | - (instancetype)init NS_UNAVAILABLE; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/VPInteractiveImageViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // VPInteractiveImageViewController.m 3 | // VPInteractiveImageViewController 4 | // 5 | // Created by Vidu Pirathaparajah on 27/01/14. 6 | // Copyright (c) 2014 Vidu Pirathaparajah. All rights reserved. 7 | // 8 | 9 | #import "VPInteractiveImageViewController.h" 10 | #import "VPInteractiveImageView.h" 11 | 12 | @interface VPInteractiveImageViewController () 13 | @property (nonatomic, weak, readonly) VPInteractiveImageView *interactiveImageView; 14 | @property (nonatomic) UIImageView *imageView; 15 | @property (nonatomic) UIScrollView *scrollView; 16 | @property (nonatomic) UITapGestureRecognizer *tapRecognizer; 17 | @property (nonatomic) CGFloat maximumZoomScale; 18 | @end 19 | 20 | @implementation VPInteractiveImageViewController 21 | 22 | #pragma mark - Initializers 23 | 24 | - (instancetype)initWithInteractiveImageView:(VPInteractiveImageView *)interactiveImageView { 25 | self = [super initWithNibName:nil bundle:nil]; 26 | if (self) { 27 | _imageView = [[UIImageView alloc] initWithFrame:CGRectZero]; 28 | _imageView.contentMode = UIViewContentModeScaleAspectFit; 29 | self.maximumZoomScale = 3.0; 30 | _interactiveImageView = interactiveImageView; 31 | } 32 | return self; 33 | } 34 | 35 | - (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil 36 | bundle:(nullable NSBundle *)nibBundleOrNil { 37 | self = [self initWithInteractiveImageView:nil]; 38 | @throw [NSException exceptionWithName:@"wrong init" reason:nil userInfo:nil]; 39 | } 40 | 41 | - (instancetype)initWithCoder:(nonnull NSCoder *)aDecoder { 42 | self = [self initWithInteractiveImageView:nil]; 43 | @throw [NSException exceptionWithName:@"wrong init" reason:nil userInfo:nil]; 44 | } 45 | 46 | - (void)dealloc { 47 | self.scrollView.delegate = nil; 48 | } 49 | 50 | - (void)viewDidLoad { 51 | [super viewDidLoad]; 52 | 53 | UITapGestureRecognizer *doubleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(viewDoubleTapped:)]; 54 | doubleTapRecognizer.numberOfTapsRequired = 2; 55 | [self.view addGestureRecognizer:doubleTapRecognizer]; 56 | _tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(viewTapped:)]; 57 | [_tapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer]; 58 | [self.view addGestureRecognizer:_tapRecognizer]; 59 | 60 | [self setupScrollView]; 61 | self.view.backgroundColor = [UIColor blackColor]; 62 | [self.scrollView addSubview:self.imageView]; 63 | 64 | [self adjustImageViewFrame]; 65 | _imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 66 | } 67 | 68 | - (void)setupScrollView { 69 | self.scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds]; 70 | self.scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 71 | self.scrollView.delegate = self; 72 | self.scrollView.maximumZoomScale = self.maximumZoomScale; 73 | [self.view addSubview:self.scrollView]; 74 | } 75 | 76 | - (void)viewTapped:(UITapGestureRecognizer *)gestureRecognizer { 77 | if ([self.interactiveImageView.delegate respondsToSelector:@selector(interactiveImageViewWillDismiss:)]) { 78 | [self.interactiveImageView.delegate performSelector:@selector(interactiveImageViewWillDismiss:) 79 | withObject:self.interactiveImageView]; 80 | } 81 | [self.presentingViewController dismissViewControllerAnimated:YES completion:NULL]; 82 | } 83 | 84 | - (void)viewDoubleTapped:(UITapGestureRecognizer *)gestureRecognizer { 85 | if (self.scrollView.zoomScale < self.scrollView.maximumZoomScale) { 86 | [self zoomInWithPoint:[gestureRecognizer locationInView:self.imageView]]; 87 | } else { 88 | [self zoomOut]; 89 | } 90 | } 91 | 92 | - (void)viewDidLayoutSubviews { 93 | [super viewDidLayoutSubviews]; 94 | 95 | self.scrollView.minimumZoomScale = [self minimumZoomScale]; 96 | if (self.scrollView.zoomScale <= [self minimumZoomScale]) { 97 | [self zoomOut]; // reset zoomScale and contentsize to original state 98 | } 99 | } 100 | 101 | - (void)zoomInWithPoint:(CGPoint)point { 102 | CGFloat newScale = self.maximumZoomScale; 103 | CGRect zoomRect = [self zoomRectForScale:newScale withCenter:point]; 104 | [self.scrollView zoomToRect:zoomRect animated:YES]; 105 | } 106 | 107 | - (void)zoomOut { 108 | self.scrollView.minimumZoomScale = [self minimumZoomScale]; 109 | [self.scrollView setZoomScale:self.scrollView.minimumZoomScale animated:YES]; 110 | self.scrollView.contentSize = self.scrollView.bounds.size; 111 | [self adjustImageViewFrame]; 112 | } 113 | 114 | - (void)adjustImageViewFrame { 115 | self.imageView.frame = CGRectMake(0, 0, 116 | self.scrollView.bounds.size.width, 117 | self.scrollView.bounds.size.height); 118 | } 119 | 120 | - (CGRect)zoomRectForScale:(CGFloat)scale withCenter:(CGPoint)center { 121 | CGRect zoomRect = CGRectZero; 122 | zoomRect.size.height = floor(self.view.bounds.size.height / scale); 123 | zoomRect.size.width = floor(self.view.bounds.size.width / scale); 124 | zoomRect.origin.x = center.x - floor(zoomRect.size.width / 2.0); 125 | zoomRect.origin.y = center.y - floor(zoomRect.size.height / 2.0); 126 | 127 | return zoomRect; 128 | } 129 | 130 | - (CGFloat)minimumZoomScale { 131 | CGFloat scale = self.scrollView.bounds.size.width / self.imageView.bounds.size.width; 132 | return scale; 133 | } 134 | 135 | #pragma mark - UIScrollViewDelegate 136 | 137 | - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { 138 | return self.imageView; 139 | } 140 | 141 | - (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view { 142 | self.tapRecognizer.enabled = NO; 143 | } 144 | 145 | - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale { 146 | if (scale <= [self minimumZoomScale]) { 147 | self.tapRecognizer.enabled = YES; 148 | } 149 | } 150 | 151 | @end 152 | -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/VPTransitionAnimator.h: -------------------------------------------------------------------------------- 1 | // 2 | // VPTransitionAnimator.h 3 | // VPInteractiveImageViewController 4 | // 5 | // Created by Vidu Pirathaparajah on 01/02/14. 6 | // Copyright (c) 2014 Vidu Pirathaparajah. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class VPInteractiveImageView; 12 | @interface VPTransitionAnimator : NSObject 13 | - (id)initWithInteractiveImageView:(VPInteractiveImageView *)interActiveImageView 14 | fullScreenImageViewView:(UIImageView *)imageView; 15 | @end 16 | -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/VPTransitionAnimator.m: -------------------------------------------------------------------------------- 1 | // 2 | // VPTransitionAnimator.m 3 | // VPInteractiveImageViewController 4 | // 5 | // Created by Vidu Pirathaparajah on 01/02/14. 6 | // Copyright (c) 2014 Vidu Pirathaparajah. All rights reserved. 7 | // 8 | 9 | #import "VPTransitionAnimator.h" 10 | #import "VPInteractiveImageView.h" 11 | 12 | @interface VPTransitionAnimator () 13 | @property (nonatomic) VPInteractiveImageView *interactiveImageView; 14 | @property (nonatomic) UIImageView *imageView; 15 | @property (nonatomic) CGRect originFrame; 16 | @end 17 | 18 | @implementation VPTransitionAnimator 19 | 20 | - (id)initWithInteractiveImageView:(VPInteractiveImageView *)interactiveImageView 21 | fullScreenImageViewView:(UIImageView *)imageView { 22 | self = [super init]; 23 | if (self) { 24 | _interactiveImageView = interactiveImageView; 25 | _imageView = imageView; 26 | } 27 | return self; 28 | } 29 | 30 | #pragma mark - UIViewControllerAnimatedTransitioning 31 | 32 | - (NSTimeInterval)transitionDuration:(id)transitionContext { 33 | return 0.33; 34 | } 35 | 36 | - (void)animateTransition:(id)transitionContext { 37 | 38 | UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; 39 | UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; 40 | 41 | if (fromViewController.presentedViewController == toViewController) { 42 | [self presentWithTransitionContext:transitionContext]; 43 | } else { 44 | [self dismissWithTransitionContext:transitionContext]; 45 | } 46 | } 47 | 48 | #pragma mark - Private methods 49 | 50 | - (void)presentWithTransitionContext:(id)transitionContext { 51 | 52 | UIView *containerView = [transitionContext containerView]; 53 | 54 | UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; 55 | UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; 56 | 57 | CGRect endFrame = [transitionContext initialFrameForViewController:fromViewController]; 58 | 59 | UIColor *backgroundColor = toViewController.view.backgroundColor; 60 | 61 | self.originFrame = [containerView convertRect:self.interactiveImageView.frame 62 | fromView:self.interactiveImageView.superview]; 63 | CGRect finalImageViewRect = self.imageView.frame; 64 | self.imageView.frame = self.originFrame; 65 | toViewController.view.frame = endFrame; 66 | toViewController.view.backgroundColor = [UIColor clearColor]; 67 | 68 | [containerView addSubview:toViewController.view]; 69 | 70 | [UIView animateWithDuration:[self transitionDuration:transitionContext] 71 | animations:^{ 72 | self.imageView.frame = finalImageViewRect; 73 | self.imageView.transform = CGAffineTransformIdentity; 74 | toViewController.view.layer.backgroundColor = [backgroundColor CGColor]; 75 | } completion:^(BOOL finished) { 76 | toViewController.view.backgroundColor = backgroundColor; 77 | [transitionContext completeTransition:![transitionContext transitionWasCancelled]]; 78 | }]; 79 | } 80 | 81 | - (void)dismissWithTransitionContext:(id)transitionContext { 82 | 83 | UIView *containerView = [transitionContext containerView]; 84 | 85 | UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; 86 | UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; 87 | 88 | CGRect endFrame = [transitionContext initialFrameForViewController:fromViewController]; 89 | 90 | [containerView addSubview:toViewController.view]; 91 | 92 | [containerView addSubview:fromViewController.view]; 93 | 94 | fromViewController.view.frame = endFrame; 95 | toViewController.view.frame = endFrame; 96 | 97 | 98 | [UIView animateWithDuration:[self transitionDuration:transitionContext] 99 | animations:^{ 100 | self.imageView.frame = [fromViewController.view convertRect:self.originFrame fromView:containerView]; 101 | fromViewController.view.layer.backgroundColor = 0; 102 | } completion:^(BOOL finished) { 103 | fromViewController.view.layer.backgroundColor = [[UIColor clearColor] CGColor]; 104 | [transitionContext completeTransition:![transitionContext transitionWasCancelled]]; 105 | }]; 106 | } 107 | 108 | @end 109 | -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/VPTransitionDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // VPTransitionDelegate.h 3 | // VPInteractiveImageViewController 4 | // 5 | // Created by Vidu Pirathaparajah on 01/02/14. 6 | // Copyright (c) 2014 Vidu Pirathaparajah. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class VPInteractiveImageView; 12 | @interface VPTransitionDelegate : NSObject 13 | @property (nonatomic, weak) UIImageView *imageView; 14 | @property (nonatomic) BOOL pinchGestureEnabled; 15 | @property (nonatomic) BOOL panCloseGestureEnabled; 16 | - (id)initWithInteractiveImageView:(VPInteractiveImageView *)interactiveImageView fullScreenImageView:(UIImageView *)imageView; 17 | @end 18 | -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/VPTransitionDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // VPTransitionDelegate.m 3 | // VPInteractiveImageViewController 4 | // 5 | // Created by Vidu Pirathaparajah on 01/02/14. 6 | // Copyright (c) 2014 Vidu Pirathaparajah. All rights reserved. 7 | // 8 | 9 | #import "VPTransitionDelegate.h" 10 | #import "VPTransitionAnimator.h" 11 | #import "VPInteractiveImageView.h" 12 | #import "VPTransitionInteractor.h" 13 | #import "VPInteractiveImageViewController.h" 14 | 15 | @interface VPTransitionDelegate () 16 | @property (nonatomic, weak) VPInteractiveImageView *interactiveImageView; 17 | @property (nonatomic) VPTransitionAnimator *transitionAnimator; 18 | @property (nonatomic) VPTransitionInteractor *presentingTransitionInteractor; 19 | @property (nonatomic) VPTransitionInteractor *dismissingTransitionInteractor; 20 | @end 21 | 22 | @implementation VPTransitionDelegate 23 | 24 | - (id)initWithInteractiveImageView:(VPInteractiveImageView *)interactiveImageView 25 | fullScreenImageView:(UIImageView *)imageView { 26 | self = [super init]; 27 | if (self) { 28 | _interactiveImageView = interactiveImageView; 29 | _imageView = imageView; 30 | _presentingTransitionInteractor = [[VPTransitionInteractor alloc] initWithViewController:nil 31 | pinchableView:_interactiveImageView]; 32 | } 33 | return self; 34 | } 35 | 36 | #pragma mark - Getter / Setter 37 | 38 | - (void)setPinchGestureEnabled:(BOOL)pinchGestureEnabled { 39 | _pinchGestureEnabled = pinchGestureEnabled; 40 | self.presentingTransitionInteractor.pinchGestureEnabled = _pinchGestureEnabled; 41 | self.dismissingTransitionInteractor.pinchGestureEnabled = _pinchGestureEnabled; 42 | } 43 | 44 | - (void)setPanCloseGestureEnabled:(BOOL)panCloseGestureEnabled { 45 | _panCloseGestureEnabled = panCloseGestureEnabled; 46 | self.dismissingTransitionInteractor.panCloseGestureEnabled = _panCloseGestureEnabled; 47 | } 48 | 49 | #pragma mark - UIViewControllerAnimatedTransitioning 50 | 51 | - (id)animationControllerForPresentedController:(UIViewController *)presented 52 | presentingController:(UIViewController *)presenting 53 | sourceController:(UIViewController *)source { 54 | self.transitionAnimator = nil; 55 | self.dismissingTransitionInteractor = [[VPTransitionInteractor alloc] initWithViewController:presented 56 | pinchableView:self.imageView]; 57 | self.dismissingTransitionInteractor.pinchGestureEnabled = self.pinchGestureEnabled; 58 | self.dismissingTransitionInteractor.panCloseGestureEnabled = self.panCloseGestureEnabled; 59 | return self.transitionAnimator; 60 | } 61 | 62 | - (id)animationControllerForDismissedController:(UIViewController *)dismissed { 63 | VPTransitionAnimator *transitionAnimator = self.transitionAnimator; 64 | return transitionAnimator; 65 | } 66 | 67 | #pragma mark - UIViewControllerInteractiveTransitioning 68 | 69 | - (id)interactionControllerForPresentation:(id )animator { 70 | if (!self.presentingTransitionInteractor.isInteractiveTransition) 71 | return nil; 72 | return self.presentingTransitionInteractor; 73 | } 74 | 75 | - (id )interactionControllerForDismissal:(id )animator { 76 | if (!self.dismissingTransitionInteractor.isInteractiveTransition) 77 | return nil; 78 | return self.dismissingTransitionInteractor; 79 | } 80 | 81 | #pragma mark - Helper methods 82 | 83 | - (VPTransitionAnimator *)transitionAnimator { 84 | if (!_transitionAnimator) { 85 | _transitionAnimator = [[VPTransitionAnimator alloc] initWithInteractiveImageView:self.interactiveImageView 86 | fullScreenImageViewView:self.imageView]; 87 | } 88 | return _transitionAnimator; 89 | } 90 | 91 | @end 92 | -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/VPTransitionInteractor.h: -------------------------------------------------------------------------------- 1 | // 2 | // VPTransitionInteractor.h 3 | // VPInteractiveImageViewController 4 | // 5 | // Created by Vidu Pirathaparajah on 16/02/14. 6 | // Copyright (c) 2014 Vidu Pirathaparajah. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class VPInteractiveImageView; 12 | @interface VPTransitionInteractor : UIPercentDrivenInteractiveTransition 13 | 14 | @property (nonatomic) BOOL isInteractiveTransition; 15 | @property (nonatomic) BOOL isPresenting; 16 | @property (nonatomic, weak) id delegate; 17 | @property (nonatomic) BOOL pinchGestureEnabled; 18 | @property (nonatomic) BOOL panCloseGestureEnabled; 19 | 20 | - (id)initWithViewController:(UIViewController *)viewController pinchableView:(UIView *)pinchableView; 21 | @end 22 | -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/VPTransitionInteractor.m: -------------------------------------------------------------------------------- 1 | // 2 | // VPTransitionInteractor.m 3 | // VPInteractiveImageViewController 4 | // 5 | // Created by Vidu Pirathaparajah on 16/02/14. 6 | // Copyright (c) 2014 Vidu Pirathaparajah. All rights reserved. 7 | // 8 | 9 | #import "VPTransitionInteractor.h" 10 | #import "VPInteractiveImageView.h" 11 | 12 | @interface VPTransitionInteractor () 13 | 14 | @property (nonatomic, weak) UIViewController *viewController; 15 | @property (nonatomic, weak) UIView *pinchableView; 16 | @property (nonatomic) CGFloat fixedScale; 17 | @property (nonatomic) CGPoint translation; 18 | @property (nonatomic) UIPinchGestureRecognizer *pinchGestureRecognizer; 19 | @property (nonatomic) UIPanGestureRecognizer *panGestureRecognizer; 20 | 21 | @end 22 | 23 | @implementation VPTransitionInteractor 24 | 25 | - (id)initWithViewController:(UIViewController *)viewController pinchableView:(UIView *)pinchableView { 26 | self = [super init]; 27 | if (self) { 28 | _viewController = viewController; 29 | _pinchableView = pinchableView; 30 | _pinchableView.userInteractionEnabled = YES; 31 | [self setupGestureRecognizer]; 32 | } 33 | return self; 34 | } 35 | 36 | - (void)setupGestureRecognizer { 37 | if (self.viewController) { 38 | self.pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self 39 | action:@selector(handlePinchClose:)]; 40 | self.pinchGestureRecognizer.delegate = self; 41 | } else { 42 | self.pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self 43 | action:@selector(handlePinchOpen:)]; 44 | } 45 | self.pinchableView.userInteractionEnabled = YES; 46 | [self.pinchableView addGestureRecognizer:self.pinchGestureRecognizer]; 47 | 48 | if (!self.viewController) 49 | return; 50 | 51 | self.panGestureRecognizer = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(handlePanClose:)]; 52 | [self.pinchableView addGestureRecognizer:self.panGestureRecognizer]; 53 | } 54 | 55 | #pragma mark - Getter / Setter 56 | 57 | - (void)setPinchGestureEnabled:(BOOL)pinchGestureEnabled { 58 | _pinchGestureEnabled = pinchGestureEnabled; 59 | self.pinchGestureRecognizer.enabled = _pinchGestureEnabled; 60 | } 61 | 62 | - (void)setPanCloseGestureEnabled:(BOOL)panCloseGestureEnabled { 63 | _panCloseGestureEnabled = panCloseGestureEnabled; 64 | self.panGestureRecognizer.enabled = _panCloseGestureEnabled; 65 | } 66 | #pragma mark - Gesture actions 67 | 68 | - (void)handlePinchOpen:(UIPinchGestureRecognizer *)pinch { 69 | CGFloat scale = pinch.scale; 70 | switch (pinch.state) { 71 | case UIGestureRecognizerStateBegan: { 72 | self.fixedScale = 5; 73 | self.isInteractiveTransition = YES; 74 | [(VPInteractiveImageView *)self.pinchableView presentFullscreen]; 75 | break; 76 | } 77 | case UIGestureRecognizerStateChanged: { 78 | CGFloat percent = (1.0f / _fixedScale) * scale; 79 | [self updateInteractiveTransition:(percent < 0.0) ? 0.0 : percent]; 80 | break; 81 | } 82 | case UIGestureRecognizerStateEnded: { 83 | CGFloat percent = (1.0f / _fixedScale) * scale; 84 | BOOL cancelled = ([pinch velocity] < 5.0 && percent <= 0.3); 85 | 86 | if (cancelled) { 87 | [self cancelInteractiveTransition]; 88 | } else { 89 | [self finishInteractiveTransition]; 90 | } 91 | self.isInteractiveTransition = NO; 92 | break; 93 | } 94 | case UIGestureRecognizerStateCancelled: 95 | case UIGestureRecognizerStateFailed: 96 | [self cancelInteractiveTransition]; 97 | self.isInteractiveTransition = NO; 98 | break; 99 | case UIGestureRecognizerStatePossible: 100 | break; 101 | } 102 | } 103 | 104 | -(void)handlePinchClose:(UIPinchGestureRecognizer *)pinch { 105 | CGFloat scale = pinch.scale; 106 | switch (pinch.state) { 107 | case UIGestureRecognizerStateBegan: { 108 | //TODO: Need to introduce a proper interface to get the scrollView 109 | UIScrollView *scrollView = (UIScrollView *)self.pinchableView.superview; 110 | if (scale >= 1 || scrollView.zoomScale > scrollView.minimumZoomScale) { 111 | pinch.enabled = NO; 112 | pinch.enabled = YES; 113 | return; 114 | } else { 115 | scrollView.pinchGestureRecognizer.enabled = NO; 116 | scrollView.pinchGestureRecognizer.enabled = YES; 117 | } 118 | self.fixedScale = scale; 119 | self.isInteractiveTransition = YES; 120 | [self.viewController dismissViewControllerAnimated:YES 121 | completion:NULL]; 122 | break; 123 | } 124 | case UIGestureRecognizerStateChanged: { 125 | CGFloat percent = (1.0 - scale/_fixedScale); 126 | [self updateInteractiveTransition:(percent < 0.0) ? 0.0 : percent]; 127 | break; 128 | } 129 | case UIGestureRecognizerStateEnded: { 130 | CGFloat percent = (1.0 - scale/_fixedScale); 131 | BOOL cancelled = ([pinch velocity] < 5.0 && percent <= 0.3); 132 | 133 | if (cancelled) { 134 | [self cancelInteractiveTransition]; 135 | } else { 136 | [self finishInteractiveTransition]; 137 | } 138 | self.isInteractiveTransition = NO; 139 | break; 140 | } 141 | case UIGestureRecognizerStateCancelled: 142 | case UIGestureRecognizerStateFailed: 143 | [self cancelInteractiveTransition]; 144 | self.isInteractiveTransition = NO; 145 | break; 146 | case UIGestureRecognizerStatePossible: 147 | break; 148 | } 149 | } 150 | 151 | - (void)handlePanClose:(UIPanGestureRecognizer *)gestureRecognizer { 152 | CGPoint currentTranlation = [gestureRecognizer translationInView:self.pinchableView];; 153 | switch (gestureRecognizer.state) { 154 | case UIGestureRecognizerStateBegan:{ 155 | //TODO: Need to introduce a proper interface to get the scrollView 156 | UIScrollView *scrollView = (UIScrollView *)self.pinchableView.superview; 157 | if (scrollView.zoomScale > scrollView.minimumZoomScale) { 158 | gestureRecognizer.enabled = NO; 159 | gestureRecognizer.enabled = YES; 160 | return; 161 | } 162 | self.translation = CGPointZero; 163 | self.isInteractiveTransition = YES; 164 | [self.viewController dismissViewControllerAnimated:YES 165 | completion:NULL]; 166 | break; 167 | } 168 | case UIGestureRecognizerStateChanged: { 169 | self.translation = CGPointMake(self.translation.x + currentTranlation.x, self.translation.y + currentTranlation.y); 170 | CGFloat percent = [self percent]; 171 | [self updateInteractiveTransition:percent]; 172 | self.pinchableView.transform = CGAffineTransformTranslate(self.pinchableView.transform, currentTranlation.x, currentTranlation.y); 173 | [gestureRecognizer setTranslation:CGPointZero inView:self.pinchableView]; 174 | break; 175 | } 176 | case UIGestureRecognizerStateEnded: { 177 | CGFloat percent; 178 | percent = [self percent]; 179 | BOOL cancelled = ([gestureRecognizer velocityInView:self.pinchableView].y < 5.0 && percent <= 0.3); 180 | if (cancelled) { 181 | [self cancelInteractiveTransition]; 182 | } else { 183 | 184 | [self finishInteractiveTransition]; 185 | } 186 | self.isInteractiveTransition = NO; 187 | break; 188 | } 189 | case UIGestureRecognizerStateCancelled: 190 | case UIGestureRecognizerStateFailed: 191 | [self cancelInteractiveTransition]; 192 | self.isInteractiveTransition = NO; 193 | break; 194 | case UIGestureRecognizerStatePossible: 195 | break; 196 | } 197 | } 198 | 199 | - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { 200 | return YES; 201 | } 202 | 203 | #pragma mark - Helper methods 204 | 205 | - (CGFloat)percent { 206 | CGFloat percent = ((1.0f/200) * self.translation.y); 207 | percent = (percent > 100) ? 100 : percent; 208 | percent = (percent < 0) ? 0 : percent; 209 | return percent; 210 | } 211 | 212 | @end 213 | -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewController/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // VPInteractiveImageViewController 4 | // 5 | // Created by Vidu Pirathaparajah on 27/01/14. 6 | // Copyright (c) 2014 Vidu Pirathaparajah. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "VPAppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([VPAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewControllerTests/VPInteractiveImageViewControllerTests-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 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewControllerTests/VPInteractiveImageViewControllerTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // VPInteractiveImageViewControllerTests.m 3 | // VPInteractiveImageViewControllerTests 4 | // 5 | // Created by Vidu Pirathaparajah on 27/01/14. 6 | // Copyright (c) 2014 Vidu Pirathaparajah. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface VPInteractiveImageViewControllerTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation VPInteractiveImageViewControllerTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /VPInteractiveImageViewController/VPInteractiveImageViewControllerTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | --------------------------------------------------------------------------------