├── DraggableViewControllerDemo.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcuserdata │ └── saiday.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── DraggableViewControllerDemo.xcscheme │ └── xcschememanagement.plist ├── DraggableViewControllerDemo ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ └── LaunchScreen.storyboard ├── BaseAnimator.h ├── BaseAnimator.m ├── DummyView.h ├── DummyView.m ├── Info.plist ├── MiniToLargeViewAnimator.h ├── MiniToLargeViewAnimator.m ├── MiniToLargeViewInteractive.h ├── MiniToLargeViewInteractive.m ├── NextViewController.h ├── NextViewController.m ├── ViewController.h ├── ViewController.m └── main.m ├── README.md └── draggable_view_controller-1.gif /DraggableViewControllerDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 83B187821BFDBCF80050F8FC /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 83B187811BFDBCF80050F8FC /* main.m */; }; 11 | 83B187851BFDBCF80050F8FC /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 83B187841BFDBCF80050F8FC /* AppDelegate.m */; }; 12 | 83B187881BFDBCF80050F8FC /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 83B187871BFDBCF80050F8FC /* ViewController.m */; }; 13 | 83B1878D1BFDBCF80050F8FC /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 83B1878C1BFDBCF80050F8FC /* Assets.xcassets */; }; 14 | 83B187901BFDBCF80050F8FC /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 83B1878E1BFDBCF80050F8FC /* LaunchScreen.storyboard */; }; 15 | 83B187991BFDBD200050F8FC /* BaseAnimator.m in Sources */ = {isa = PBXBuildFile; fileRef = 83B187981BFDBD200050F8FC /* BaseAnimator.m */; }; 16 | 83B1879C1BFDBEB20050F8FC /* MiniToLargeViewAnimator.m in Sources */ = {isa = PBXBuildFile; fileRef = 83B1879B1BFDBEB20050F8FC /* MiniToLargeViewAnimator.m */; }; 17 | 83B187A21BFDBFD10050F8FC /* NextViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 83B187A11BFDBFD10050F8FC /* NextViewController.m */; }; 18 | 83B187A51BFDC0BE0050F8FC /* MiniToLargeViewInteractive.m in Sources */ = {isa = PBXBuildFile; fileRef = 83B187A41BFDC0BE0050F8FC /* MiniToLargeViewInteractive.m */; }; 19 | 83B187AB1BFE0DC00050F8FC /* DummyView.m in Sources */ = {isa = PBXBuildFile; fileRef = 83B187AA1BFE0DC00050F8FC /* DummyView.m */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXFileReference section */ 23 | 83B1877D1BFDBCF80050F8FC /* DraggableViewControllerDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DraggableViewControllerDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 24 | 83B187811BFDBCF80050F8FC /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 25 | 83B187831BFDBCF80050F8FC /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 26 | 83B187841BFDBCF80050F8FC /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 27 | 83B187861BFDBCF80050F8FC /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 28 | 83B187871BFDBCF80050F8FC /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 29 | 83B1878C1BFDBCF80050F8FC /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 30 | 83B1878F1BFDBCF80050F8FC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 31 | 83B187911BFDBCF80050F8FC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 32 | 83B187971BFDBD200050F8FC /* BaseAnimator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BaseAnimator.h; sourceTree = ""; }; 33 | 83B187981BFDBD200050F8FC /* BaseAnimator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BaseAnimator.m; sourceTree = ""; }; 34 | 83B1879A1BFDBEB20050F8FC /* MiniToLargeViewAnimator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MiniToLargeViewAnimator.h; sourceTree = ""; }; 35 | 83B1879B1BFDBEB20050F8FC /* MiniToLargeViewAnimator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MiniToLargeViewAnimator.m; sourceTree = ""; }; 36 | 83B187A01BFDBFD10050F8FC /* NextViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NextViewController.h; sourceTree = ""; }; 37 | 83B187A11BFDBFD10050F8FC /* NextViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NextViewController.m; sourceTree = ""; }; 38 | 83B187A31BFDC0BE0050F8FC /* MiniToLargeViewInteractive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MiniToLargeViewInteractive.h; sourceTree = ""; }; 39 | 83B187A41BFDC0BE0050F8FC /* MiniToLargeViewInteractive.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MiniToLargeViewInteractive.m; sourceTree = ""; }; 40 | 83B187A91BFE0DC00050F8FC /* DummyView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DummyView.h; sourceTree = ""; }; 41 | 83B187AA1BFE0DC00050F8FC /* DummyView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DummyView.m; sourceTree = ""; }; 42 | /* End PBXFileReference section */ 43 | 44 | /* Begin PBXFrameworksBuildPhase section */ 45 | 83B1877A1BFDBCF80050F8FC /* Frameworks */ = { 46 | isa = PBXFrameworksBuildPhase; 47 | buildActionMask = 2147483647; 48 | files = ( 49 | ); 50 | runOnlyForDeploymentPostprocessing = 0; 51 | }; 52 | /* End PBXFrameworksBuildPhase section */ 53 | 54 | /* Begin PBXGroup section */ 55 | 83B187741BFDBCF80050F8FC = { 56 | isa = PBXGroup; 57 | children = ( 58 | 83B1877F1BFDBCF80050F8FC /* DraggableViewControllerDemo */, 59 | 83B1877E1BFDBCF80050F8FC /* Products */, 60 | ); 61 | sourceTree = ""; 62 | }; 63 | 83B1877E1BFDBCF80050F8FC /* Products */ = { 64 | isa = PBXGroup; 65 | children = ( 66 | 83B1877D1BFDBCF80050F8FC /* DraggableViewControllerDemo.app */, 67 | ); 68 | name = Products; 69 | sourceTree = ""; 70 | }; 71 | 83B1877F1BFDBCF80050F8FC /* DraggableViewControllerDemo */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | 83B187831BFDBCF80050F8FC /* AppDelegate.h */, 75 | 83B187841BFDBCF80050F8FC /* AppDelegate.m */, 76 | 83B187861BFDBCF80050F8FC /* ViewController.h */, 77 | 83B187871BFDBCF80050F8FC /* ViewController.m */, 78 | 83B187A01BFDBFD10050F8FC /* NextViewController.h */, 79 | 83B187A11BFDBFD10050F8FC /* NextViewController.m */, 80 | 83B187971BFDBD200050F8FC /* BaseAnimator.h */, 81 | 83B187981BFDBD200050F8FC /* BaseAnimator.m */, 82 | 83B1879A1BFDBEB20050F8FC /* MiniToLargeViewAnimator.h */, 83 | 83B1879B1BFDBEB20050F8FC /* MiniToLargeViewAnimator.m */, 84 | 83B187A31BFDC0BE0050F8FC /* MiniToLargeViewInteractive.h */, 85 | 83B187A41BFDC0BE0050F8FC /* MiniToLargeViewInteractive.m */, 86 | 83B187A91BFE0DC00050F8FC /* DummyView.h */, 87 | 83B187AA1BFE0DC00050F8FC /* DummyView.m */, 88 | 83B1878C1BFDBCF80050F8FC /* Assets.xcassets */, 89 | 83B1878E1BFDBCF80050F8FC /* LaunchScreen.storyboard */, 90 | 83B187911BFDBCF80050F8FC /* Info.plist */, 91 | 83B187801BFDBCF80050F8FC /* Supporting Files */, 92 | ); 93 | path = DraggableViewControllerDemo; 94 | sourceTree = ""; 95 | }; 96 | 83B187801BFDBCF80050F8FC /* Supporting Files */ = { 97 | isa = PBXGroup; 98 | children = ( 99 | 83B187811BFDBCF80050F8FC /* main.m */, 100 | ); 101 | name = "Supporting Files"; 102 | sourceTree = ""; 103 | }; 104 | /* End PBXGroup section */ 105 | 106 | /* Begin PBXNativeTarget section */ 107 | 83B1877C1BFDBCF80050F8FC /* DraggableViewControllerDemo */ = { 108 | isa = PBXNativeTarget; 109 | buildConfigurationList = 83B187941BFDBCF80050F8FC /* Build configuration list for PBXNativeTarget "DraggableViewControllerDemo" */; 110 | buildPhases = ( 111 | 83B187791BFDBCF80050F8FC /* Sources */, 112 | 83B1877A1BFDBCF80050F8FC /* Frameworks */, 113 | 83B1877B1BFDBCF80050F8FC /* Resources */, 114 | ); 115 | buildRules = ( 116 | ); 117 | dependencies = ( 118 | ); 119 | name = DraggableViewControllerDemo; 120 | productName = DraggableViewControllerDemo; 121 | productReference = 83B1877D1BFDBCF80050F8FC /* DraggableViewControllerDemo.app */; 122 | productType = "com.apple.product-type.application"; 123 | }; 124 | /* End PBXNativeTarget section */ 125 | 126 | /* Begin PBXProject section */ 127 | 83B187751BFDBCF80050F8FC /* Project object */ = { 128 | isa = PBXProject; 129 | attributes = { 130 | LastUpgradeCheck = 0710; 131 | ORGANIZATIONNAME = saiday; 132 | TargetAttributes = { 133 | 83B1877C1BFDBCF80050F8FC = { 134 | CreatedOnToolsVersion = 7.1.1; 135 | }; 136 | }; 137 | }; 138 | buildConfigurationList = 83B187781BFDBCF80050F8FC /* Build configuration list for PBXProject "DraggableViewControllerDemo" */; 139 | compatibilityVersion = "Xcode 3.2"; 140 | developmentRegion = English; 141 | hasScannedForEncodings = 0; 142 | knownRegions = ( 143 | en, 144 | Base, 145 | ); 146 | mainGroup = 83B187741BFDBCF80050F8FC; 147 | productRefGroup = 83B1877E1BFDBCF80050F8FC /* Products */; 148 | projectDirPath = ""; 149 | projectRoot = ""; 150 | targets = ( 151 | 83B1877C1BFDBCF80050F8FC /* DraggableViewControllerDemo */, 152 | ); 153 | }; 154 | /* End PBXProject section */ 155 | 156 | /* Begin PBXResourcesBuildPhase section */ 157 | 83B1877B1BFDBCF80050F8FC /* Resources */ = { 158 | isa = PBXResourcesBuildPhase; 159 | buildActionMask = 2147483647; 160 | files = ( 161 | 83B187901BFDBCF80050F8FC /* LaunchScreen.storyboard in Resources */, 162 | 83B1878D1BFDBCF80050F8FC /* Assets.xcassets in Resources */, 163 | ); 164 | runOnlyForDeploymentPostprocessing = 0; 165 | }; 166 | /* End PBXResourcesBuildPhase section */ 167 | 168 | /* Begin PBXSourcesBuildPhase section */ 169 | 83B187791BFDBCF80050F8FC /* Sources */ = { 170 | isa = PBXSourcesBuildPhase; 171 | buildActionMask = 2147483647; 172 | files = ( 173 | 83B187881BFDBCF80050F8FC /* ViewController.m in Sources */, 174 | 83B187851BFDBCF80050F8FC /* AppDelegate.m in Sources */, 175 | 83B1879C1BFDBEB20050F8FC /* MiniToLargeViewAnimator.m in Sources */, 176 | 83B187A21BFDBFD10050F8FC /* NextViewController.m in Sources */, 177 | 83B187821BFDBCF80050F8FC /* main.m in Sources */, 178 | 83B187AB1BFE0DC00050F8FC /* DummyView.m in Sources */, 179 | 83B187A51BFDC0BE0050F8FC /* MiniToLargeViewInteractive.m in Sources */, 180 | 83B187991BFDBD200050F8FC /* BaseAnimator.m in Sources */, 181 | ); 182 | runOnlyForDeploymentPostprocessing = 0; 183 | }; 184 | /* End PBXSourcesBuildPhase section */ 185 | 186 | /* Begin PBXVariantGroup section */ 187 | 83B1878E1BFDBCF80050F8FC /* LaunchScreen.storyboard */ = { 188 | isa = PBXVariantGroup; 189 | children = ( 190 | 83B1878F1BFDBCF80050F8FC /* Base */, 191 | ); 192 | name = LaunchScreen.storyboard; 193 | sourceTree = ""; 194 | }; 195 | /* End PBXVariantGroup section */ 196 | 197 | /* Begin XCBuildConfiguration section */ 198 | 83B187921BFDBCF80050F8FC /* Debug */ = { 199 | isa = XCBuildConfiguration; 200 | buildSettings = { 201 | ALWAYS_SEARCH_USER_PATHS = NO; 202 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 203 | CLANG_CXX_LIBRARY = "libc++"; 204 | CLANG_ENABLE_MODULES = YES; 205 | CLANG_ENABLE_OBJC_ARC = YES; 206 | CLANG_WARN_BOOL_CONVERSION = YES; 207 | CLANG_WARN_CONSTANT_CONVERSION = YES; 208 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 209 | CLANG_WARN_EMPTY_BODY = YES; 210 | CLANG_WARN_ENUM_CONVERSION = YES; 211 | CLANG_WARN_INT_CONVERSION = YES; 212 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 213 | CLANG_WARN_UNREACHABLE_CODE = YES; 214 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 215 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 216 | COPY_PHASE_STRIP = NO; 217 | DEBUG_INFORMATION_FORMAT = dwarf; 218 | ENABLE_STRICT_OBJC_MSGSEND = YES; 219 | ENABLE_TESTABILITY = YES; 220 | GCC_C_LANGUAGE_STANDARD = gnu99; 221 | GCC_DYNAMIC_NO_PIC = NO; 222 | GCC_NO_COMMON_BLOCKS = YES; 223 | GCC_OPTIMIZATION_LEVEL = 0; 224 | GCC_PREPROCESSOR_DEFINITIONS = ( 225 | "DEBUG=1", 226 | "$(inherited)", 227 | ); 228 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 229 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 230 | GCC_WARN_UNDECLARED_SELECTOR = YES; 231 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 232 | GCC_WARN_UNUSED_FUNCTION = YES; 233 | GCC_WARN_UNUSED_VARIABLE = YES; 234 | IPHONEOS_DEPLOYMENT_TARGET = 9.1; 235 | MTL_ENABLE_DEBUG_INFO = YES; 236 | ONLY_ACTIVE_ARCH = YES; 237 | SDKROOT = iphoneos; 238 | TARGETED_DEVICE_FAMILY = "1,2"; 239 | }; 240 | name = Debug; 241 | }; 242 | 83B187931BFDBCF80050F8FC /* Release */ = { 243 | isa = XCBuildConfiguration; 244 | buildSettings = { 245 | ALWAYS_SEARCH_USER_PATHS = NO; 246 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 247 | CLANG_CXX_LIBRARY = "libc++"; 248 | CLANG_ENABLE_MODULES = YES; 249 | CLANG_ENABLE_OBJC_ARC = YES; 250 | CLANG_WARN_BOOL_CONVERSION = YES; 251 | CLANG_WARN_CONSTANT_CONVERSION = YES; 252 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 253 | CLANG_WARN_EMPTY_BODY = YES; 254 | CLANG_WARN_ENUM_CONVERSION = YES; 255 | CLANG_WARN_INT_CONVERSION = YES; 256 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 257 | CLANG_WARN_UNREACHABLE_CODE = YES; 258 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 259 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 260 | COPY_PHASE_STRIP = NO; 261 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 262 | ENABLE_NS_ASSERTIONS = NO; 263 | ENABLE_STRICT_OBJC_MSGSEND = YES; 264 | GCC_C_LANGUAGE_STANDARD = gnu99; 265 | GCC_NO_COMMON_BLOCKS = YES; 266 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 267 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 268 | GCC_WARN_UNDECLARED_SELECTOR = YES; 269 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 270 | GCC_WARN_UNUSED_FUNCTION = YES; 271 | GCC_WARN_UNUSED_VARIABLE = YES; 272 | IPHONEOS_DEPLOYMENT_TARGET = 9.1; 273 | MTL_ENABLE_DEBUG_INFO = NO; 274 | SDKROOT = iphoneos; 275 | TARGETED_DEVICE_FAMILY = "1,2"; 276 | VALIDATE_PRODUCT = YES; 277 | }; 278 | name = Release; 279 | }; 280 | 83B187951BFDBCF80050F8FC /* Debug */ = { 281 | isa = XCBuildConfiguration; 282 | buildSettings = { 283 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 284 | INFOPLIST_FILE = DraggableViewControllerDemo/Info.plist; 285 | IPHONEOS_DEPLOYMENT_TARGET = 9.1; 286 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 287 | PRODUCT_BUNDLE_IDENTIFIER = com.saiday.DraggableViewControllerDemo; 288 | PRODUCT_NAME = "$(TARGET_NAME)"; 289 | }; 290 | name = Debug; 291 | }; 292 | 83B187961BFDBCF80050F8FC /* Release */ = { 293 | isa = XCBuildConfiguration; 294 | buildSettings = { 295 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 296 | INFOPLIST_FILE = DraggableViewControllerDemo/Info.plist; 297 | IPHONEOS_DEPLOYMENT_TARGET = 9.1; 298 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 299 | PRODUCT_BUNDLE_IDENTIFIER = com.saiday.DraggableViewControllerDemo; 300 | PRODUCT_NAME = "$(TARGET_NAME)"; 301 | }; 302 | name = Release; 303 | }; 304 | /* End XCBuildConfiguration section */ 305 | 306 | /* Begin XCConfigurationList section */ 307 | 83B187781BFDBCF80050F8FC /* Build configuration list for PBXProject "DraggableViewControllerDemo" */ = { 308 | isa = XCConfigurationList; 309 | buildConfigurations = ( 310 | 83B187921BFDBCF80050F8FC /* Debug */, 311 | 83B187931BFDBCF80050F8FC /* Release */, 312 | ); 313 | defaultConfigurationIsVisible = 0; 314 | defaultConfigurationName = Release; 315 | }; 316 | 83B187941BFDBCF80050F8FC /* Build configuration list for PBXNativeTarget "DraggableViewControllerDemo" */ = { 317 | isa = XCConfigurationList; 318 | buildConfigurations = ( 319 | 83B187951BFDBCF80050F8FC /* Debug */, 320 | 83B187961BFDBCF80050F8FC /* Release */, 321 | ); 322 | defaultConfigurationIsVisible = 0; 323 | }; 324 | /* End XCConfigurationList section */ 325 | }; 326 | rootObject = 83B187751BFDBCF80050F8FC /* Project object */; 327 | } 328 | -------------------------------------------------------------------------------- /DraggableViewControllerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /DraggableViewControllerDemo.xcodeproj/xcuserdata/saiday.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /DraggableViewControllerDemo.xcodeproj/xcuserdata/saiday.xcuserdatad/xcschemes/DraggableViewControllerDemo.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 | -------------------------------------------------------------------------------- /DraggableViewControllerDemo.xcodeproj/xcuserdata/saiday.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | DraggableViewControllerDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 83B1877C1BFDBCF80050F8FC 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /DraggableViewControllerDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // DraggableViewControllerDemo 4 | // 5 | // Created by saiday on 11/19/15. 6 | // Copyright © 2015 saiday. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /DraggableViewControllerDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // DraggableViewControllerDemo 4 | // 5 | // Created by saiday on 11/19/15. 6 | // Copyright © 2015 saiday. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | #import "ViewController.h" 12 | 13 | @interface AppDelegate () 14 | 15 | @end 16 | 17 | @implementation AppDelegate 18 | 19 | 20 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 21 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 22 | [self.window setRootViewController:[[ViewController alloc] init]]; 23 | [self.window makeKeyAndVisible]; 24 | return YES; 25 | } 26 | 27 | - (void)applicationWillResignActive:(UIApplication *)application { 28 | // 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. 29 | // 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. 30 | } 31 | 32 | - (void)applicationDidEnterBackground:(UIApplication *)application { 33 | // 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. 34 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 35 | } 36 | 37 | - (void)applicationWillEnterForeground:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // 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. 43 | } 44 | 45 | - (void)applicationWillTerminate:(UIApplication *)application { 46 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /DraggableViewControllerDemo/Assets.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" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /DraggableViewControllerDemo/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 | -------------------------------------------------------------------------------- /DraggableViewControllerDemo/BaseAnimator.h: -------------------------------------------------------------------------------- 1 | // 2 | // BaseAnimator.h 3 | // DraggableViewControllerDemo 4 | // 5 | // Created by saiday on 11/19/15. 6 | // Copyright © 2015 saiday. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSInteger, ModalAnimatedTransitioningType) { 12 | ModalAnimatedTransitioningTypePresent, 13 | ModalAnimatedTransitioningTypeDismiss 14 | }; 15 | 16 | @interface BaseAnimator : NSObject 17 | 18 | @property (nonatomic) ModalAnimatedTransitioningType transitionType; 19 | 20 | - (void)animatePresentingInContext:(id)transitionContext toVC:(UIViewController *)toVC fromVC:(UIViewController *)fromVC; 21 | - (void)animateDismissingInContext:(id)transitionContext toVC:(UIViewController *)toVC fromVC:(UIViewController *)fromVC; 22 | 23 | @end -------------------------------------------------------------------------------- /DraggableViewControllerDemo/BaseAnimator.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseAnimator.m 3 | // DraggableViewControllerDemo 4 | // 5 | // Created by saiday on 11/19/15. 6 | // Copyright © 2015 saiday. All rights reserved. 7 | // 8 | 9 | #import "BaseAnimator.h" 10 | 11 | @implementation BaseAnimator 12 | 13 | - (void)animateTransition:(id)transitionContext 14 | { 15 | UIViewController *to = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; 16 | UIViewController *from = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; 17 | 18 | if (self.transitionType == ModalAnimatedTransitioningTypePresent) { 19 | [self animatePresentingInContext:transitionContext toVC:to fromVC:from]; 20 | } else if (self.transitionType == ModalAnimatedTransitioningTypeDismiss) { 21 | [self animateDismissingInContext:transitionContext toVC:to fromVC:from]; 22 | } 23 | } 24 | 25 | - (NSTimeInterval)transitionDuration:(id)transitionContext 26 | { 27 | // mustOverride() 28 | // mustOverride() is a marco took from stackoverflow Yar's answer, or you can use nicklockwood's solution MustOverride GitHub. You can left it blank as well, what mustOverride() does is throw an exception when we forget override the method in subclass. 29 | // http://stackoverflow.com/questions/1034373/creating-an-abstract-class-in-objective-c/6448761#6448761 30 | 31 | @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"%s must be overridden in a subclass/category", __PRETTY_FUNCTION__] userInfo:nil]; 32 | } 33 | 34 | - (void)animatePresentingInContext:(id)transitionContext toVC:(UIViewController *)toVC fromVC:(UIViewController *)fromVC 35 | { 36 | @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"%s must be overridden in a subclass/category", __PRETTY_FUNCTION__] userInfo:nil]; 37 | } 38 | 39 | - (void)animateDismissingInContext:(id)transitionContext toVC:(UIViewController *)toVC fromVC:(UIViewController *)fromVC 40 | { 41 | @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"%s must be overridden in a subclass/category", __PRETTY_FUNCTION__] userInfo:nil]; 42 | } 43 | 44 | @end -------------------------------------------------------------------------------- /DraggableViewControllerDemo/DummyView.h: -------------------------------------------------------------------------------- 1 | // 2 | // DummyView.h 3 | // DraggableViewControllerDemo 4 | // 5 | // Created by saiday on 11/19/15. 6 | // Copyright © 2015 saiday. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DummyView : UIView 12 | 13 | @property (nonatomic, weak) UIButton *button; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /DraggableViewControllerDemo/DummyView.m: -------------------------------------------------------------------------------- 1 | // 2 | // DummyView.m 3 | // DraggableViewControllerDemo 4 | // 5 | // Created by saiday on 11/19/15. 6 | // Copyright © 2015 saiday. All rights reserved. 7 | // 8 | 9 | #import "DummyView.h" 10 | 11 | @implementation DummyView 12 | 13 | - (instancetype)initWithFrame:(CGRect)frame 14 | { 15 | self = [super initWithFrame:frame]; 16 | if (self) { 17 | [self setupSubview]; 18 | } 19 | 20 | return self; 21 | } 22 | 23 | - (void)setupSubview 24 | { 25 | UIButton *bottomButton = [UIButton buttonWithType:UIButtonTypeCustom]; 26 | bottomButton.translatesAutoresizingMaskIntoConstraints = NO; 27 | bottomButton.backgroundColor = [UIColor grayColor]; 28 | [bottomButton setTitle:@"Tap or drag me" forState:UIControlStateNormal]; 29 | [self addSubview:bottomButton]; 30 | [self addConstraint:[NSLayoutConstraint constraintWithItem:bottomButton attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:bottomButton.superview attribute:NSLayoutAttributeTop multiplier:1.0 constant:0]]; 31 | [self addConstraint:[NSLayoutConstraint constraintWithItem:bottomButton attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:bottomButton.superview attribute:NSLayoutAttributeRight multiplier:1.0 constant:0]]; 32 | [self addConstraint:[NSLayoutConstraint constraintWithItem:bottomButton attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:bottomButton.superview attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0]]; 33 | [self addConstraint:[NSLayoutConstraint constraintWithItem:bottomButton attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:bottomButton.superview attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0]]; 34 | 35 | self.button = bottomButton; 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /DraggableViewControllerDemo/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 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /DraggableViewControllerDemo/MiniToLargeViewAnimator.h: -------------------------------------------------------------------------------- 1 | // 2 | // MiniToLargeViewAnimator.h 3 | // DraggableViewControllerDemo 4 | // 5 | // Created by saiday on 11/19/15. 6 | // Copyright © 2015 saiday. All rights reserved. 7 | // 8 | 9 | #import "BaseAnimator.h" 10 | 11 | @interface MiniToLargeViewAnimator : BaseAnimator 12 | 13 | @property (nonatomic) CGFloat initialY; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /DraggableViewControllerDemo/MiniToLargeViewAnimator.m: -------------------------------------------------------------------------------- 1 | // 2 | // MiniToLargeViewAnimator.m 3 | // DraggableViewControllerDemo 4 | // 5 | // Created by saiday on 11/19/15. 6 | // Copyright © 2015 saiday. All rights reserved. 7 | // 8 | 9 | #import "MiniToLargeViewAnimator.h" 10 | 11 | #import "DummyView.h" 12 | 13 | static NSTimeInterval kAnimationDuration = .4f; 14 | 15 | @implementation MiniToLargeViewAnimator 16 | 17 | - (NSTimeInterval)transitionDuration:(id)transitionContext 18 | { 19 | return kAnimationDuration; 20 | } 21 | 22 | - (void)animatePresentingInContext:(id)transitionContext toVC:(UIViewController *)toVC fromVC:(UIViewController *)fromVC 23 | { 24 | CGRect fromVCRect = [transitionContext initialFrameForViewController:fromVC]; 25 | CGRect toVCRect = fromVCRect; 26 | toVCRect.origin.y = toVCRect.size.height - self.initialY; 27 | 28 | toVC.view.frame = toVCRect; 29 | UIView *container = [transitionContext containerView]; 30 | UIView *imageView = [self fakeMiniView]; 31 | [toVC.view addSubview:imageView]; 32 | [container addSubview:fromVC.view]; 33 | [container addSubview:toVC.view]; 34 | 35 | [UIView animateWithDuration:kAnimationDuration animations:^{ 36 | toVC.view.frame = fromVCRect; 37 | imageView.alpha = 0.f; 38 | } completion:^(BOOL finished) { 39 | [imageView removeFromSuperview]; 40 | if ([transitionContext transitionWasCancelled]) { 41 | [transitionContext completeTransition:NO]; 42 | } else { 43 | [transitionContext completeTransition:YES]; 44 | } 45 | }]; 46 | } 47 | 48 | - (void)animateDismissingInContext:(id)transitionContext toVC:(UIViewController *)toVC fromVC:(UIViewController *)fromVC 49 | { 50 | CGRect fromVCRect = [transitionContext initialFrameForViewController:fromVC]; 51 | fromVCRect.origin.y = fromVCRect.size.height - self.initialY; 52 | 53 | UIView *imageView = [self fakeMiniView]; 54 | [fromVC.view addSubview:imageView]; 55 | UIView *container = [transitionContext containerView]; 56 | [container addSubview:toVC.view]; 57 | [container addSubview:fromVC.view]; 58 | imageView.alpha = 0.f; 59 | 60 | [UIView animateWithDuration:kAnimationDuration animations:^{ 61 | fromVC.view.frame = fromVCRect; 62 | imageView.alpha = 1.f; 63 | } completion:^(BOOL finished) { 64 | [imageView removeFromSuperview]; 65 | if ([transitionContext transitionWasCancelled]) { 66 | [transitionContext completeTransition:NO]; 67 | [toVC.view removeFromSuperview]; 68 | } else { 69 | [transitionContext completeTransition:YES]; 70 | } 71 | }]; 72 | } 73 | 74 | - (UIView *)fakeMiniView 75 | { 76 | // Fake a mini view, two ways: 77 | // 1. create a new certain one 78 | // 2. snapshot old one. 79 | 80 | DummyView *dummyView = [[DummyView alloc] initWithFrame:CGRectMake(0.f, 0.f, [[UIScreen mainScreen] bounds].size.width, 50.f)]; 81 | return dummyView; 82 | } 83 | 84 | @end 85 | -------------------------------------------------------------------------------- /DraggableViewControllerDemo/MiniToLargeViewInteractive.h: -------------------------------------------------------------------------------- 1 | // 2 | // MiniToLargeViewInteractive.h 3 | // DraggableViewControllerDemo 4 | // 5 | // Created by saiday on 11/19/15. 6 | // Copyright © 2015 saiday. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MiniToLargeViewInteractive : UIPercentDrivenInteractiveTransition 12 | 13 | @property (nonatomic) UIViewController *viewController; 14 | @property (nonatomic) UIViewController *presentViewController; 15 | @property (nonatomic) UIPanGestureRecognizer *pan; 16 | 17 | - (void)attachToViewController:(UIViewController *)viewController withView:(UIView *)view presentViewController:(UIViewController *)presentViewController; 18 | 19 | @end -------------------------------------------------------------------------------- /DraggableViewControllerDemo/MiniToLargeViewInteractive.m: -------------------------------------------------------------------------------- 1 | // 2 | // MiniToLargeViewInteractive.m 3 | // DraggableViewControllerDemo 4 | // 5 | // Created by saiday on 11/19/15. 6 | // Copyright © 2015 saiday. All rights reserved. 7 | // 8 | 9 | #import "MiniToLargeViewInteractive.h" 10 | 11 | @interface MiniToLargeViewInteractive () 12 | 13 | @property (nonatomic) BOOL shouldComplete; 14 | 15 | @end 16 | 17 | @implementation MiniToLargeViewInteractive 18 | 19 | - (void)attachToViewController:(UIViewController *)viewController withView:(UIView *)view presentViewController:(UIViewController *)presentViewController 20 | { 21 | self.viewController = viewController; 22 | self.presentViewController = presentViewController; 23 | self.pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(onPan:)]; 24 | [view addGestureRecognizer:self.pan]; 25 | } 26 | 27 | - (void)onPan:(UIPanGestureRecognizer *)pan 28 | { 29 | CGPoint translation = [pan translationInView:pan.view.superview]; 30 | 31 | switch (pan.state) { 32 | case UIGestureRecognizerStateBegan: 33 | if (!self.presentViewController) { 34 | [self.viewController dismissViewControllerAnimated:YES completion:nil]; 35 | } else { 36 | [self.viewController presentViewController:self.presentViewController animated:YES completion:nil]; 37 | } 38 | break; 39 | 40 | case UIGestureRecognizerStateChanged: 41 | { 42 | const CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height - 50.f; 43 | const CGFloat DragAmount = !self.presentViewController ? screenHeight : - screenHeight; 44 | const CGFloat Threshold = .3f; 45 | CGFloat percent = translation.y / DragAmount; 46 | 47 | percent = fmaxf(percent, 0.f); 48 | percent = fminf(percent, 1.f); 49 | [self updateInteractiveTransition:percent]; 50 | 51 | self.shouldComplete = percent > Threshold; 52 | } 53 | break; 54 | 55 | case UIGestureRecognizerStateEnded: 56 | case UIGestureRecognizerStateCancelled: 57 | { 58 | if (pan.state == UIGestureRecognizerStateCancelled || !self.shouldComplete) { 59 | [self cancelInteractiveTransition]; 60 | } else { 61 | [self finishInteractiveTransition]; 62 | } 63 | } 64 | break; 65 | default: 66 | break; 67 | } 68 | } 69 | 70 | - (CGFloat)completionSpeed 71 | { 72 | return 1.f - self.percentComplete; 73 | } 74 | 75 | @end -------------------------------------------------------------------------------- /DraggableViewControllerDemo/NextViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // NewViewController.h 3 | // DraggableViewControllerDemo 4 | // 5 | // Created by saiday on 11/19/15. 6 | // Copyright © 2015 saiday. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "ViewController.h" 12 | 13 | @interface NextViewController : UIViewController 14 | 15 | @property (nonatomic, weak) ViewController *rootViewController; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /DraggableViewControllerDemo/NextViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // NewViewController.m 3 | // DraggableViewControllerDemo 4 | // 5 | // Created by saiday on 11/19/15. 6 | // Copyright © 2015 saiday. All rights reserved. 7 | // 8 | 9 | #import "NextViewController.h" 10 | 11 | @interface NextViewController () 12 | 13 | @property (nonatomic, weak) UIButton *bottomButton; 14 | 15 | @end 16 | 17 | @implementation NextViewController 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | 22 | self.view.backgroundColor = [UIColor yellowColor]; 23 | 24 | UIButton *dismissButton = [UIButton buttonWithType:UIButtonTypeCustom]; 25 | dismissButton.translatesAutoresizingMaskIntoConstraints = NO; 26 | dismissButton.backgroundColor = [UIColor grayColor]; 27 | [dismissButton setTitle:@"Dismiss" forState:UIControlStateNormal]; 28 | [dismissButton addTarget:self action:@selector(bottomButtonTapped) forControlEvents:UIControlEventTouchUpInside]; 29 | [self.view addSubview:dismissButton]; 30 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:dismissButton attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.f]]; 31 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:dismissButton attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.f]]; 32 | 33 | self.bottomButton = dismissButton; 34 | } 35 | 36 | - (void)bottomButtonTapped 37 | { 38 | self.rootViewController.disableInteractivePlayerTransitioning = YES; 39 | __weak typeof(self) weakSelf = self; 40 | [self dismissViewControllerAnimated:YES completion:^{ 41 | weakSelf.rootViewController.disableInteractivePlayerTransitioning = NO; 42 | }]; 43 | } 44 | 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /DraggableViewControllerDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // DraggableViewControllerDemo 4 | // 5 | // Created by saiday on 11/19/15. 6 | // Copyright © 2015 saiday. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | @property (nonatomic) BOOL disableInteractivePlayerTransitioning; 14 | 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /DraggableViewControllerDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // DraggableViewControllerDemo 4 | // 5 | // Created by saiday on 11/19/15. 6 | // Copyright © 2015 saiday. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | #import "DummyView.h" 12 | #import "NextViewController.h" 13 | #import "MiniToLargeViewAnimator.h" 14 | #import "MiniToLargeViewInteractive.h" 15 | 16 | static CGFloat kButtonHeight = 50.f; 17 | 18 | @interface ViewController () 19 | 20 | @property (nonatomic) NextViewController *nextViewController; 21 | @property (nonatomic) MiniToLargeViewInteractive *presentInteractor; 22 | @property (nonatomic) MiniToLargeViewInteractive *dismissInteractor; 23 | 24 | @property (nonatomic, weak) UIView *dummyView; 25 | 26 | @end 27 | 28 | @implementation ViewController 29 | 30 | - (void)viewDidLoad { 31 | [super viewDidLoad]; 32 | 33 | DummyView *dummyView = [[DummyView alloc] init]; 34 | dummyView.translatesAutoresizingMaskIntoConstraints = NO; 35 | [dummyView.button addTarget:self action:@selector(bottomButtonTapped) forControlEvents:UIControlEventTouchUpInside]; 36 | [self.view addSubview:dummyView]; 37 | [dummyView addConstraint:[NSLayoutConstraint constraintWithItem:dummyView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.f constant:kButtonHeight]]; 38 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:dummyView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:dummyView.superview attribute:NSLayoutAttributeRight multiplier:1.0 constant:0]]; 39 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:dummyView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:dummyView.superview attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0]]; 40 | [self.view addConstraint:[NSLayoutConstraint constraintWithItem:dummyView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:dummyView.superview attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0]]; 41 | self.dummyView = dummyView; 42 | 43 | self.nextViewController = [[NextViewController alloc] init]; 44 | self.nextViewController.rootViewController = self; 45 | self.nextViewController.transitioningDelegate = self; 46 | self.nextViewController.modalTransitionStyle = UIModalPresentationCustom; 47 | self.nextViewController.modalPresentationStyle = UIModalPresentationFullScreen; 48 | 49 | self.presentInteractor = [[MiniToLargeViewInteractive alloc] init]; 50 | [self.presentInteractor attachToViewController:self withView:dummyView presentViewController:self.nextViewController]; 51 | self.dismissInteractor = [[MiniToLargeViewInteractive alloc] init]; 52 | [self.dismissInteractor attachToViewController:self.nextViewController withView:self.nextViewController.view presentViewController:nil]; 53 | } 54 | 55 | - (void)bottomButtonTapped 56 | { 57 | self.disableInteractivePlayerTransitioning = YES; 58 | [self presentViewController:self.nextViewController animated:YES completion:^{ 59 | self.disableInteractivePlayerTransitioning = NO; 60 | }]; 61 | } 62 | 63 | - (id)animationControllerForDismissedController:(UIViewController *)dismissed 64 | { 65 | MiniToLargeViewAnimator *animator = [[MiniToLargeViewAnimator alloc] init]; 66 | animator.initialY = kButtonHeight; 67 | animator.transitionType = ModalAnimatedTransitioningTypeDismiss; 68 | return animator; 69 | } 70 | 71 | - (id)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source 72 | { 73 | MiniToLargeViewAnimator *animator = [[MiniToLargeViewAnimator alloc] init]; 74 | animator.initialY = kButtonHeight; 75 | animator.transitionType = ModalAnimatedTransitioningTypePresent; 76 | return animator; 77 | } 78 | 79 | - (id)interactionControllerForPresentation:(id)animator 80 | { 81 | if (self.disableInteractivePlayerTransitioning) { 82 | return nil; 83 | } 84 | return self.presentInteractor; 85 | } 86 | 87 | - (id)interactionControllerForDismissal:(id)animator 88 | { 89 | if (self.disableInteractivePlayerTransitioning) { 90 | return nil; 91 | } 92 | return self.dismissInteractor; 93 | } 94 | 95 | @end 96 | -------------------------------------------------------------------------------- /DraggableViewControllerDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // DraggableViewControllerDemo 4 | // 5 | // Created by saiday on 11/19/15. 6 | // Copyright © 2015 saiday. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is a demo project for my blog post [Draggable view controller? Interactive view controller!](http://imnotyourson.com/draggable-view-controller-interactive-view-controller/) 2 | 3 | If you'd prefer Swift version, here you go: [Swift version](https://github.com/ostatnicky/DraggableViewController) made by [ostathnicky](https://github.com/ostatnicky/) 4 | 5 | ![](draggable_view_controller-1.gif) 6 | -------------------------------------------------------------------------------- /draggable_view_controller-1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saiday/DraggableViewControllerDemo/7a61b3b1a00816df123ac2133e2f254d8d738d8c/draggable_view_controller-1.gif --------------------------------------------------------------------------------