├── .gitignore ├── PullableView.xcodeproj └── project.pbxproj ├── PullableView ├── AppDelegate.h ├── AppDelegate.m ├── PullableView-Info.plist ├── PullableView-Prefix.pch ├── PullableView.h ├── PullableView.m ├── StyledPullableView.h ├── StyledPullableView.m ├── ViewController.h ├── ViewController.m ├── background.png ├── background@2x.png ├── en.lproj │ ├── InfoPlist.strings │ ├── ViewController_iPad.xib │ └── ViewController_iPhone.xib └── main.m └── README /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.swp 3 | *~.nib 4 | 5 | xcuserdata/ 6 | 7 | *.mode1v3 8 | *.pbxuser 9 | build/ 10 | *.perspectivev3 11 | *.perspective 12 | 13 | *.xcuserstate 14 | 15 | *.mode2v3 16 | project.xcworkspace/ 17 | *.orig -------------------------------------------------------------------------------- /PullableView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 15AF6C5714C9AB8400BC1DB4 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15AF6C5614C9AB8400BC1DB4 /* UIKit.framework */; }; 11 | 15AF6C5914C9AB8400BC1DB4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15AF6C5814C9AB8400BC1DB4 /* Foundation.framework */; }; 12 | 15AF6C5B14C9AB8400BC1DB4 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15AF6C5A14C9AB8400BC1DB4 /* CoreGraphics.framework */; }; 13 | 15AF6C6114C9AB8400BC1DB4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 15AF6C5F14C9AB8400BC1DB4 /* InfoPlist.strings */; }; 14 | 15AF6C6314C9AB8400BC1DB4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 15AF6C6214C9AB8400BC1DB4 /* main.m */; }; 15 | 15AF6C6714C9AB8400BC1DB4 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 15AF6C6614C9AB8400BC1DB4 /* AppDelegate.m */; }; 16 | 15AF6C6A14C9AB8400BC1DB4 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 15AF6C6914C9AB8400BC1DB4 /* ViewController.m */; }; 17 | 15AF6C6D14C9AB8400BC1DB4 /* ViewController_iPhone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 15AF6C6B14C9AB8400BC1DB4 /* ViewController_iPhone.xib */; }; 18 | 15AF6C7014C9AB8400BC1DB4 /* ViewController_iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 15AF6C6E14C9AB8400BC1DB4 /* ViewController_iPad.xib */; }; 19 | 15AF6C7814C9ABB600BC1DB4 /* PullableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 15AF6C7714C9ABB600BC1DB4 /* PullableView.m */; }; 20 | 15AF6C7B14C9ACF500BC1DB4 /* StyledPullableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 15AF6C7A14C9ACF500BC1DB4 /* StyledPullableView.m */; }; 21 | 15AF6C7E14C9B29700BC1DB4 /* background.png in Resources */ = {isa = PBXBuildFile; fileRef = 15AF6C7C14C9B29700BC1DB4 /* background.png */; }; 22 | 15AF6C7F14C9B29700BC1DB4 /* background@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 15AF6C7D14C9B29700BC1DB4 /* background@2x.png */; }; 23 | /* End PBXBuildFile section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | 15AF6C5214C9AB8400BC1DB4 /* PullableView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PullableView.app; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | 15AF6C5614C9AB8400BC1DB4 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 28 | 15AF6C5814C9AB8400BC1DB4 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 29 | 15AF6C5A14C9AB8400BC1DB4 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 30 | 15AF6C5E14C9AB8400BC1DB4 /* PullableView-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "PullableView-Info.plist"; sourceTree = ""; }; 31 | 15AF6C6014C9AB8400BC1DB4 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 32 | 15AF6C6214C9AB8400BC1DB4 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 33 | 15AF6C6414C9AB8400BC1DB4 /* PullableView-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "PullableView-Prefix.pch"; sourceTree = ""; }; 34 | 15AF6C6514C9AB8400BC1DB4 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 35 | 15AF6C6614C9AB8400BC1DB4 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 36 | 15AF6C6814C9AB8400BC1DB4 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 37 | 15AF6C6914C9AB8400BC1DB4 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 38 | 15AF6C6C14C9AB8400BC1DB4 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/ViewController_iPhone.xib; sourceTree = ""; }; 39 | 15AF6C6F14C9AB8400BC1DB4 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/ViewController_iPad.xib; sourceTree = ""; }; 40 | 15AF6C7614C9ABB600BC1DB4 /* PullableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PullableView.h; sourceTree = ""; }; 41 | 15AF6C7714C9ABB600BC1DB4 /* PullableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PullableView.m; sourceTree = ""; }; 42 | 15AF6C7914C9ACF500BC1DB4 /* StyledPullableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyledPullableView.h; sourceTree = ""; }; 43 | 15AF6C7A14C9ACF500BC1DB4 /* StyledPullableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StyledPullableView.m; sourceTree = ""; }; 44 | 15AF6C7C14C9B29700BC1DB4 /* background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = background.png; sourceTree = ""; }; 45 | 15AF6C7D14C9B29700BC1DB4 /* background@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "background@2x.png"; sourceTree = ""; }; 46 | /* End PBXFileReference section */ 47 | 48 | /* Begin PBXFrameworksBuildPhase section */ 49 | 15AF6C4F14C9AB8400BC1DB4 /* Frameworks */ = { 50 | isa = PBXFrameworksBuildPhase; 51 | buildActionMask = 2147483647; 52 | files = ( 53 | 15AF6C5714C9AB8400BC1DB4 /* UIKit.framework in Frameworks */, 54 | 15AF6C5914C9AB8400BC1DB4 /* Foundation.framework in Frameworks */, 55 | 15AF6C5B14C9AB8400BC1DB4 /* CoreGraphics.framework in Frameworks */, 56 | ); 57 | runOnlyForDeploymentPostprocessing = 0; 58 | }; 59 | /* End PBXFrameworksBuildPhase section */ 60 | 61 | /* Begin PBXGroup section */ 62 | 15AF6C4714C9AB8400BC1DB4 = { 63 | isa = PBXGroup; 64 | children = ( 65 | 15AF6C5C14C9AB8400BC1DB4 /* PullableView */, 66 | 15AF6C5514C9AB8400BC1DB4 /* Frameworks */, 67 | 15AF6C5314C9AB8400BC1DB4 /* Products */, 68 | ); 69 | sourceTree = ""; 70 | }; 71 | 15AF6C5314C9AB8400BC1DB4 /* Products */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | 15AF6C5214C9AB8400BC1DB4 /* PullableView.app */, 75 | ); 76 | name = Products; 77 | sourceTree = ""; 78 | }; 79 | 15AF6C5514C9AB8400BC1DB4 /* Frameworks */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 15AF6C5614C9AB8400BC1DB4 /* UIKit.framework */, 83 | 15AF6C5814C9AB8400BC1DB4 /* Foundation.framework */, 84 | 15AF6C5A14C9AB8400BC1DB4 /* CoreGraphics.framework */, 85 | ); 86 | name = Frameworks; 87 | sourceTree = ""; 88 | }; 89 | 15AF6C5C14C9AB8400BC1DB4 /* PullableView */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | 15AF6C7614C9ABB600BC1DB4 /* PullableView.h */, 93 | 15AF6C7714C9ABB600BC1DB4 /* PullableView.m */, 94 | 15AF6C7914C9ACF500BC1DB4 /* StyledPullableView.h */, 95 | 15AF6C7A14C9ACF500BC1DB4 /* StyledPullableView.m */, 96 | 15AF6C6514C9AB8400BC1DB4 /* AppDelegate.h */, 97 | 15AF6C6614C9AB8400BC1DB4 /* AppDelegate.m */, 98 | 15AF6C6814C9AB8400BC1DB4 /* ViewController.h */, 99 | 15AF6C6914C9AB8400BC1DB4 /* ViewController.m */, 100 | 15AF6C6B14C9AB8400BC1DB4 /* ViewController_iPhone.xib */, 101 | 15AF6C6E14C9AB8400BC1DB4 /* ViewController_iPad.xib */, 102 | 15AF6C5D14C9AB8400BC1DB4 /* Supporting Files */, 103 | ); 104 | path = PullableView; 105 | sourceTree = ""; 106 | }; 107 | 15AF6C5D14C9AB8400BC1DB4 /* Supporting Files */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 15AF6C7C14C9B29700BC1DB4 /* background.png */, 111 | 15AF6C7D14C9B29700BC1DB4 /* background@2x.png */, 112 | 15AF6C5E14C9AB8400BC1DB4 /* PullableView-Info.plist */, 113 | 15AF6C5F14C9AB8400BC1DB4 /* InfoPlist.strings */, 114 | 15AF6C6214C9AB8400BC1DB4 /* main.m */, 115 | 15AF6C6414C9AB8400BC1DB4 /* PullableView-Prefix.pch */, 116 | ); 117 | name = "Supporting Files"; 118 | sourceTree = ""; 119 | }; 120 | /* End PBXGroup section */ 121 | 122 | /* Begin PBXNativeTarget section */ 123 | 15AF6C5114C9AB8400BC1DB4 /* PullableView */ = { 124 | isa = PBXNativeTarget; 125 | buildConfigurationList = 15AF6C7314C9AB8400BC1DB4 /* Build configuration list for PBXNativeTarget "PullableView" */; 126 | buildPhases = ( 127 | 15AF6C4E14C9AB8400BC1DB4 /* Sources */, 128 | 15AF6C4F14C9AB8400BC1DB4 /* Frameworks */, 129 | 15AF6C5014C9AB8400BC1DB4 /* Resources */, 130 | ); 131 | buildRules = ( 132 | ); 133 | dependencies = ( 134 | ); 135 | name = PullableView; 136 | productName = PullableView; 137 | productReference = 15AF6C5214C9AB8400BC1DB4 /* PullableView.app */; 138 | productType = "com.apple.product-type.application"; 139 | }; 140 | /* End PBXNativeTarget section */ 141 | 142 | /* Begin PBXProject section */ 143 | 15AF6C4914C9AB8400BC1DB4 /* Project object */ = { 144 | isa = PBXProject; 145 | attributes = { 146 | LastUpgradeCheck = 0420; 147 | }; 148 | buildConfigurationList = 15AF6C4C14C9AB8400BC1DB4 /* Build configuration list for PBXProject "PullableView" */; 149 | compatibilityVersion = "Xcode 3.2"; 150 | developmentRegion = English; 151 | hasScannedForEncodings = 0; 152 | knownRegions = ( 153 | en, 154 | ); 155 | mainGroup = 15AF6C4714C9AB8400BC1DB4; 156 | productRefGroup = 15AF6C5314C9AB8400BC1DB4 /* Products */; 157 | projectDirPath = ""; 158 | projectRoot = ""; 159 | targets = ( 160 | 15AF6C5114C9AB8400BC1DB4 /* PullableView */, 161 | ); 162 | }; 163 | /* End PBXProject section */ 164 | 165 | /* Begin PBXResourcesBuildPhase section */ 166 | 15AF6C5014C9AB8400BC1DB4 /* Resources */ = { 167 | isa = PBXResourcesBuildPhase; 168 | buildActionMask = 2147483647; 169 | files = ( 170 | 15AF6C6114C9AB8400BC1DB4 /* InfoPlist.strings in Resources */, 171 | 15AF6C6D14C9AB8400BC1DB4 /* ViewController_iPhone.xib in Resources */, 172 | 15AF6C7014C9AB8400BC1DB4 /* ViewController_iPad.xib in Resources */, 173 | 15AF6C7E14C9B29700BC1DB4 /* background.png in Resources */, 174 | 15AF6C7F14C9B29700BC1DB4 /* background@2x.png in Resources */, 175 | ); 176 | runOnlyForDeploymentPostprocessing = 0; 177 | }; 178 | /* End PBXResourcesBuildPhase section */ 179 | 180 | /* Begin PBXSourcesBuildPhase section */ 181 | 15AF6C4E14C9AB8400BC1DB4 /* Sources */ = { 182 | isa = PBXSourcesBuildPhase; 183 | buildActionMask = 2147483647; 184 | files = ( 185 | 15AF6C6314C9AB8400BC1DB4 /* main.m in Sources */, 186 | 15AF6C6714C9AB8400BC1DB4 /* AppDelegate.m in Sources */, 187 | 15AF6C6A14C9AB8400BC1DB4 /* ViewController.m in Sources */, 188 | 15AF6C7814C9ABB600BC1DB4 /* PullableView.m in Sources */, 189 | 15AF6C7B14C9ACF500BC1DB4 /* StyledPullableView.m in Sources */, 190 | ); 191 | runOnlyForDeploymentPostprocessing = 0; 192 | }; 193 | /* End PBXSourcesBuildPhase section */ 194 | 195 | /* Begin PBXVariantGroup section */ 196 | 15AF6C5F14C9AB8400BC1DB4 /* InfoPlist.strings */ = { 197 | isa = PBXVariantGroup; 198 | children = ( 199 | 15AF6C6014C9AB8400BC1DB4 /* en */, 200 | ); 201 | name = InfoPlist.strings; 202 | sourceTree = ""; 203 | }; 204 | 15AF6C6B14C9AB8400BC1DB4 /* ViewController_iPhone.xib */ = { 205 | isa = PBXVariantGroup; 206 | children = ( 207 | 15AF6C6C14C9AB8400BC1DB4 /* en */, 208 | ); 209 | name = ViewController_iPhone.xib; 210 | sourceTree = ""; 211 | }; 212 | 15AF6C6E14C9AB8400BC1DB4 /* ViewController_iPad.xib */ = { 213 | isa = PBXVariantGroup; 214 | children = ( 215 | 15AF6C6F14C9AB8400BC1DB4 /* en */, 216 | ); 217 | name = ViewController_iPad.xib; 218 | sourceTree = ""; 219 | }; 220 | /* End PBXVariantGroup section */ 221 | 222 | /* Begin XCBuildConfiguration section */ 223 | 15AF6C7114C9AB8400BC1DB4 /* Debug */ = { 224 | isa = XCBuildConfiguration; 225 | buildSettings = { 226 | ALWAYS_SEARCH_USER_PATHS = NO; 227 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 228 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 229 | COPY_PHASE_STRIP = NO; 230 | GCC_C_LANGUAGE_STANDARD = gnu99; 231 | GCC_DYNAMIC_NO_PIC = NO; 232 | GCC_OPTIMIZATION_LEVEL = 0; 233 | GCC_PREPROCESSOR_DEFINITIONS = ( 234 | "DEBUG=1", 235 | "$(inherited)", 236 | ); 237 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 238 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 239 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 240 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 241 | GCC_WARN_UNUSED_VARIABLE = YES; 242 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 243 | SDKROOT = iphoneos; 244 | TARGETED_DEVICE_FAMILY = "1,2"; 245 | }; 246 | name = Debug; 247 | }; 248 | 15AF6C7214C9AB8400BC1DB4 /* Release */ = { 249 | isa = XCBuildConfiguration; 250 | buildSettings = { 251 | ALWAYS_SEARCH_USER_PATHS = NO; 252 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 253 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 254 | COPY_PHASE_STRIP = YES; 255 | GCC_C_LANGUAGE_STANDARD = gnu99; 256 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 257 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 258 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 259 | GCC_WARN_UNUSED_VARIABLE = YES; 260 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 261 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 262 | SDKROOT = iphoneos; 263 | TARGETED_DEVICE_FAMILY = "1,2"; 264 | VALIDATE_PRODUCT = YES; 265 | }; 266 | name = Release; 267 | }; 268 | 15AF6C7414C9AB8400BC1DB4 /* Debug */ = { 269 | isa = XCBuildConfiguration; 270 | buildSettings = { 271 | CLANG_ENABLE_OBJC_ARC = YES; 272 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 273 | GCC_PREFIX_HEADER = "PullableView/PullableView-Prefix.pch"; 274 | INFOPLIST_FILE = "PullableView/PullableView-Info.plist"; 275 | IPHONEOS_DEPLOYMENT_TARGET = 3.2; 276 | PRODUCT_NAME = "$(TARGET_NAME)"; 277 | WRAPPER_EXTENSION = app; 278 | }; 279 | name = Debug; 280 | }; 281 | 15AF6C7514C9AB8400BC1DB4 /* Release */ = { 282 | isa = XCBuildConfiguration; 283 | buildSettings = { 284 | CLANG_ENABLE_OBJC_ARC = YES; 285 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 286 | GCC_PREFIX_HEADER = "PullableView/PullableView-Prefix.pch"; 287 | INFOPLIST_FILE = "PullableView/PullableView-Info.plist"; 288 | IPHONEOS_DEPLOYMENT_TARGET = 3.2; 289 | PRODUCT_NAME = "$(TARGET_NAME)"; 290 | WRAPPER_EXTENSION = app; 291 | }; 292 | name = Release; 293 | }; 294 | /* End XCBuildConfiguration section */ 295 | 296 | /* Begin XCConfigurationList section */ 297 | 15AF6C4C14C9AB8400BC1DB4 /* Build configuration list for PBXProject "PullableView" */ = { 298 | isa = XCConfigurationList; 299 | buildConfigurations = ( 300 | 15AF6C7114C9AB8400BC1DB4 /* Debug */, 301 | 15AF6C7214C9AB8400BC1DB4 /* Release */, 302 | ); 303 | defaultConfigurationIsVisible = 0; 304 | defaultConfigurationName = Release; 305 | }; 306 | 15AF6C7314C9AB8400BC1DB4 /* Build configuration list for PBXNativeTarget "PullableView" */ = { 307 | isa = XCConfigurationList; 308 | buildConfigurations = ( 309 | 15AF6C7414C9AB8400BC1DB4 /* Debug */, 310 | 15AF6C7514C9AB8400BC1DB4 /* Release */, 311 | ); 312 | defaultConfigurationIsVisible = 0; 313 | defaultConfigurationName = Release; 314 | }; 315 | /* End XCConfigurationList section */ 316 | }; 317 | rootObject = 15AF6C4914C9AB8400BC1DB4 /* Project object */; 318 | } 319 | -------------------------------------------------------------------------------- /PullableView/AppDelegate.h: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | 4 | /** 5 | @author Fabio Rodella fabio@crocodella.com.br 6 | */ 7 | 8 | @class ViewController; 9 | 10 | @interface AppDelegate : UIResponder 11 | 12 | @property (strong, nonatomic) UIWindow *window; 13 | 14 | @property (strong, nonatomic) ViewController *viewController; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /PullableView/AppDelegate.m: -------------------------------------------------------------------------------- 1 | 2 | #import "AppDelegate.h" 3 | 4 | #import "ViewController.h" 5 | 6 | /** 7 | @author Fabio Rodella fabio@crocodella.com.br 8 | */ 9 | 10 | @implementation AppDelegate 11 | 12 | @synthesize window = _window; 13 | @synthesize viewController = _viewController; 14 | 15 | 16 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 17 | { 18 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 19 | // Override point for customization after application launch. 20 | if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { 21 | self.viewController = [[ViewController alloc] initWithNibName:@"ViewController_iPhone" bundle:nil]; 22 | } else { 23 | self.viewController = [[ViewController alloc] initWithNibName:@"ViewController_iPad" bundle:nil]; 24 | } 25 | self.window.rootViewController = self.viewController; 26 | [self.window makeKeyAndVisible]; 27 | return YES; 28 | } 29 | 30 | - (void)applicationWillResignActive:(UIApplication *)application 31 | { 32 | /* 33 | 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. 34 | 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. 35 | */ 36 | } 37 | 38 | - (void)applicationDidEnterBackground:(UIApplication *)application 39 | { 40 | /* 41 | 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. 42 | If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 43 | */ 44 | } 45 | 46 | - (void)applicationWillEnterForeground:(UIApplication *)application 47 | { 48 | /* 49 | 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. 50 | */ 51 | } 52 | 53 | - (void)applicationDidBecomeActive:(UIApplication *)application 54 | { 55 | /* 56 | 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. 57 | */ 58 | } 59 | 60 | - (void)applicationWillTerminate:(UIApplication *)application 61 | { 62 | /* 63 | Called when the application is about to terminate. 64 | Save data if appropriate. 65 | See also applicationDidEnterBackground:. 66 | */ 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /PullableView/PullableView-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFiles 12 | 13 | CFBundleIdentifier 14 | br.com.crocodella.${PRODUCT_NAME:rfc1034identifier} 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | ${PRODUCT_NAME} 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | 1.0 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | 1.0 27 | LSRequiresIPhoneOS 28 | 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationPortraitUpsideDown 37 | 38 | UISupportedInterfaceOrientations~ipad 39 | 40 | UIInterfaceOrientationPortrait 41 | UIInterfaceOrientationPortraitUpsideDown 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /PullableView/PullableView-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'PullableView' target in the 'PullableView' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_4_0 8 | #warning "This project uses features only available in iOS SDK 4.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /PullableView/PullableView.h: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | 4 | @class PullableView; 5 | 6 | /** 7 | Protocol for objects that wish to be notified when the state of a 8 | PullableView changes 9 | */ 10 | @protocol PullableViewDelegate 11 | 12 | /** 13 | Notifies of a changed state 14 | @param pView PullableView whose state was changed 15 | @param opened The new state of the view 16 | */ 17 | - (void)pullableView:(PullableView *)pView didChangeState:(BOOL)opened; 18 | 19 | @end 20 | 21 | /** 22 | Class that implements a view that can be pulled out by a handle, 23 | similar to the Notification Center in iOS 5. This class supports 24 | pulling in the horizontal or vertical axis. This is determined by 25 | the values for openedCenter and closedCenter that you set: if 26 | both have the same x coordinate, the pulling should happen in the 27 | vertical axis, or the horizontal axis otherwise. 28 | @author Fabio Rodella fabio@crocodella.com.br 29 | */ 30 | @interface PullableView : UIView { 31 | 32 | CGPoint closedCenter; 33 | CGPoint openedCenter; 34 | 35 | UIView *handleView; 36 | UIPanGestureRecognizer *dragRecognizer; 37 | UITapGestureRecognizer *tapRecognizer; 38 | 39 | CGPoint startPos; 40 | CGPoint minPos; 41 | CGPoint maxPos; 42 | 43 | BOOL opened; 44 | BOOL verticalAxis; 45 | 46 | BOOL toggleOnTap; 47 | 48 | BOOL animate; 49 | float animationDuration; 50 | 51 | id __unsafe_unretained delegate; 52 | } 53 | 54 | /** 55 | The view that is used as the handle for the PullableView. You 56 | can style it, add subviews or set its frame at will. 57 | */ 58 | @property (nonatomic,readonly) UIView *handleView; 59 | 60 | /** 61 | The point that defines the center of the view when in its closed 62 | state. You must set this before using the PullableView. 63 | */ 64 | @property (readwrite,assign) CGPoint closedCenter; 65 | 66 | /** 67 | The point that defines the center of the view when in its opened 68 | state. You must set this before using the PullableView. 69 | */ 70 | @property (readwrite,assign) CGPoint openedCenter; 71 | 72 | /** 73 | Gesture recognizer responsible for the dragging of the handle view. 74 | It is exposed as a property so you can change the number of touches 75 | or created dependencies to other recognizers in your views. 76 | */ 77 | @property (nonatomic,readonly) UIPanGestureRecognizer *dragRecognizer; 78 | 79 | /** 80 | Gesture recognizer responsible for handling tapping of the handle view. 81 | It is exposed as a property so you can change the number of touches 82 | or created dependencies to other recognizers in your views. 83 | */ 84 | @property (nonatomic,readonly) UITapGestureRecognizer *tapRecognizer; 85 | 86 | /** 87 | If set to YES, tapping the handle view will toggle the PullableView. 88 | Default value is YES. 89 | */ 90 | @property (readwrite,assign) BOOL toggleOnTap; 91 | 92 | /** 93 | If set to YES, the opening or closing of the PullableView will 94 | be animated. Default value is YES. 95 | */ 96 | @property (readwrite,assign) BOOL animate; 97 | 98 | /** 99 | Duration of the opening/closing animation, if enabled. Default 100 | value is 0.2. 101 | */ 102 | @property (readwrite,assign) float animationDuration; 103 | 104 | /** 105 | Delegate that will be notified when the PullableView changes state. 106 | If the view is set to animate transitions, the delegate will be 107 | called only when the animation finishes. 108 | */ 109 | @property (readwrite,unsafe_unretained) id delegate; 110 | 111 | /** 112 | The current state of the `PullableView`. 113 | */ 114 | @property (readonly, assign) BOOL opened; 115 | 116 | /** 117 | Toggles the state of the PullableView 118 | @param op New state of the view 119 | @param anim Flag indicating if the transition should be animated 120 | */ 121 | - (void)setOpened:(BOOL)op animated:(BOOL)anim; 122 | 123 | @end 124 | -------------------------------------------------------------------------------- /PullableView/PullableView.m: -------------------------------------------------------------------------------- 1 | 2 | #import "PullableView.h" 3 | 4 | /** 5 | @author Fabio Rodella fabio@crocodella.com.br 6 | */ 7 | 8 | @implementation PullableView 9 | 10 | @synthesize handleView; 11 | @synthesize closedCenter; 12 | @synthesize openedCenter; 13 | @synthesize dragRecognizer; 14 | @synthesize tapRecognizer; 15 | @synthesize animate; 16 | @synthesize animationDuration; 17 | @synthesize delegate; 18 | @synthesize opened; 19 | 20 | - (id)initWithFrame:(CGRect)frame 21 | { 22 | self = [super initWithFrame:frame]; 23 | if (self) { 24 | 25 | animate = YES; 26 | animationDuration = 0.2; 27 | 28 | toggleOnTap = YES; 29 | 30 | // Creates the handle view. Subclasses should resize, reposition and style this view 31 | handleView = [[UIView alloc] initWithFrame:CGRectMake(0, frame.size.height - 40, frame.size.width, 40)]; 32 | [self addSubview:handleView]; 33 | 34 | dragRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleDrag:)]; 35 | dragRecognizer.minimumNumberOfTouches = 1; 36 | dragRecognizer.maximumNumberOfTouches = 1; 37 | 38 | [handleView addGestureRecognizer:dragRecognizer]; 39 | 40 | tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]; 41 | tapRecognizer.numberOfTapsRequired = 1; 42 | tapRecognizer.numberOfTouchesRequired = 1; 43 | 44 | [handleView addGestureRecognizer:tapRecognizer]; 45 | 46 | opened = NO; 47 | } 48 | return self; 49 | } 50 | 51 | - (void)handleDrag:(UIPanGestureRecognizer *)sender { 52 | 53 | if ([sender state] == UIGestureRecognizerStateBegan) { 54 | 55 | startPos = self.center; 56 | 57 | // Determines if the view can be pulled in the x or y axis 58 | verticalAxis = closedCenter.x == openedCenter.x; 59 | 60 | // Finds the minimum and maximum points in the axis 61 | if (verticalAxis) { 62 | minPos = closedCenter.y < openedCenter.y ? closedCenter : openedCenter; 63 | maxPos = closedCenter.y > openedCenter.y ? closedCenter : openedCenter; 64 | } else { 65 | minPos = closedCenter.x < openedCenter.x ? closedCenter : openedCenter; 66 | maxPos = closedCenter.x > openedCenter.x ? closedCenter : openedCenter; 67 | } 68 | 69 | } else if ([sender state] == UIGestureRecognizerStateChanged) { 70 | 71 | CGPoint translate = [sender translationInView:self.superview]; 72 | 73 | CGPoint newPos; 74 | 75 | // Moves the view, keeping it constrained between openedCenter and closedCenter 76 | if (verticalAxis) { 77 | 78 | newPos = CGPointMake(startPos.x, startPos.y + translate.y); 79 | 80 | if (newPos.y < minPos.y) { 81 | newPos.y = minPos.y; 82 | translate = CGPointMake(0, newPos.y - startPos.y); 83 | } 84 | 85 | if (newPos.y > maxPos.y) { 86 | newPos.y = maxPos.y; 87 | translate = CGPointMake(0, newPos.y - startPos.y); 88 | } 89 | } else { 90 | 91 | newPos = CGPointMake(startPos.x + translate.x, startPos.y); 92 | 93 | if (newPos.x < minPos.x) { 94 | newPos.x = minPos.x; 95 | translate = CGPointMake(newPos.x - startPos.x, 0); 96 | } 97 | 98 | if (newPos.x > maxPos.x) { 99 | newPos.x = maxPos.x; 100 | translate = CGPointMake(newPos.x - startPos.x, 0); 101 | } 102 | } 103 | 104 | [sender setTranslation:translate inView:self.superview]; 105 | 106 | self.center = newPos; 107 | 108 | } else if ([sender state] == UIGestureRecognizerStateEnded) { 109 | 110 | // Gets the velocity of the gesture in the axis, so it can be 111 | // determined to which endpoint the state should be set. 112 | 113 | CGPoint vectorVelocity = [sender velocityInView:self.superview]; 114 | CGFloat axisVelocity = verticalAxis ? vectorVelocity.y : vectorVelocity.x; 115 | 116 | CGPoint target = axisVelocity < 0 ? minPos : maxPos; 117 | BOOL op = CGPointEqualToPoint(target, openedCenter); 118 | 119 | [self setOpened:op animated:animate]; 120 | } 121 | } 122 | 123 | - (void)handleTap:(UITapGestureRecognizer *)sender { 124 | 125 | if ([sender state] == UIGestureRecognizerStateEnded) { 126 | [self setOpened:!opened animated:animate]; 127 | } 128 | } 129 | 130 | - (void)setToggleOnTap:(BOOL)tap { 131 | toggleOnTap = tap; 132 | tapRecognizer.enabled = tap; 133 | } 134 | 135 | - (BOOL)toggleOnTap { 136 | return toggleOnTap; 137 | } 138 | 139 | - (void)setOpened:(BOOL)op animated:(BOOL)anim { 140 | opened = op; 141 | 142 | if (anim) { 143 | [UIView beginAnimations:nil context:nil]; 144 | [UIView setAnimationDuration:animationDuration]; 145 | [UIView setAnimationCurve:UIViewAnimationCurveEaseOut]; 146 | [UIView setAnimationDelegate:self]; 147 | [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)]; 148 | } 149 | 150 | self.center = opened ? openedCenter : closedCenter; 151 | 152 | if (anim) { 153 | 154 | // For the duration of the animation, no further interaction with the view is permitted 155 | dragRecognizer.enabled = NO; 156 | tapRecognizer.enabled = NO; 157 | 158 | [UIView commitAnimations]; 159 | 160 | } else { 161 | 162 | if ([delegate respondsToSelector:@selector(pullableView:didChangeState:)]) { 163 | [delegate pullableView:self didChangeState:opened]; 164 | } 165 | } 166 | } 167 | 168 | - (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { 169 | if (finished) { 170 | // Restores interaction after the animation is over 171 | dragRecognizer.enabled = YES; 172 | tapRecognizer.enabled = toggleOnTap; 173 | 174 | if ([delegate respondsToSelector:@selector(pullableView:didChangeState:)]) { 175 | [delegate pullableView:self didChangeState:opened]; 176 | } 177 | } 178 | } 179 | 180 | @end 181 | -------------------------------------------------------------------------------- /PullableView/StyledPullableView.h: -------------------------------------------------------------------------------- 1 | 2 | #import "PullableView.h" 3 | 4 | /** 5 | Subclass of PullableView that uses a background image 6 | @author Fabio Rodella fabio@crocodella.com.br 7 | */ 8 | @interface StyledPullableView : PullableView 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /PullableView/StyledPullableView.m: -------------------------------------------------------------------------------- 1 | 2 | #import "StyledPullableView.h" 3 | 4 | /** 5 | @author Fabio Rodella fabio@crocodella.com.br 6 | */ 7 | 8 | @implementation StyledPullableView 9 | 10 | - (id)initWithFrame:(CGRect)frame { 11 | if ((self = [super initWithFrame:frame])) { 12 | 13 | UIImageView *imgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"background.png"]]; 14 | imgView.frame = CGRectMake(0, 0, 320, 460); 15 | [self addSubview:imgView]; 16 | } 17 | return self; 18 | } 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /PullableView/ViewController.h: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | #import "StyledPullableView.h" 4 | 5 | /** 6 | Sample view controller 7 | @author Fabio Rodella fabio@crocodella.com.br 8 | */ 9 | 10 | @interface ViewController : UIViewController { 11 | StyledPullableView *pullDownView; 12 | 13 | StyledPullableView *pullUpView; 14 | UILabel *pullUpLabel; 15 | 16 | PullableView *pullRightView; 17 | } 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /PullableView/ViewController.m: -------------------------------------------------------------------------------- 1 | 2 | #import "ViewController.h" 3 | 4 | /** 5 | @author Fabio Rodella fabio@crocodella.com.br 6 | */ 7 | 8 | @implementation ViewController 9 | 10 | - (void)viewDidLoad 11 | { 12 | [super viewDidLoad]; 13 | 14 | CGFloat xOffset = 0; 15 | if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { 16 | xOffset = 224; 17 | } 18 | 19 | pullRightView = [[PullableView alloc] initWithFrame:CGRectMake(0, 200, 200, 300)]; 20 | pullRightView.backgroundColor = [UIColor lightGrayColor]; 21 | pullRightView.openedCenter = CGPointMake(100, 200); 22 | pullRightView.closedCenter = CGPointMake(-70, 200); 23 | pullRightView.center = pullRightView.closedCenter; 24 | pullRightView.animate = NO; 25 | 26 | pullRightView.handleView.backgroundColor = [UIColor darkGrayColor]; 27 | pullRightView.handleView.frame = CGRectMake(170, 0, 30, 300); 28 | 29 | [self.view addSubview:pullRightView]; 30 | 31 | UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 30)]; 32 | label.backgroundColor = [UIColor darkGrayColor]; 33 | label.textColor = [UIColor whiteColor]; 34 | label.text = @"Pull me to the right!"; 35 | label.transform = CGAffineTransformMakeRotation(-M_PI_2); 36 | label.center = CGPointMake(185, 150); 37 | 38 | [pullRightView addSubview:label]; 39 | 40 | label = [[UILabel alloc] initWithFrame:CGRectMake(4, 120, 200, 30)]; 41 | label.backgroundColor = [UIColor clearColor]; 42 | label.textColor = [UIColor whiteColor]; 43 | label.text = @"I'm not animated"; 44 | 45 | [pullRightView addSubview:label]; 46 | 47 | pullUpView = [[StyledPullableView alloc] initWithFrame:CGRectMake(xOffset, 0, 320, 460)]; 48 | pullUpView.openedCenter = CGPointMake(160 + xOffset,self.view.frame.size.height); 49 | pullUpView.closedCenter = CGPointMake(160 + xOffset, self.view.frame.size.height + 200); 50 | pullUpView.center = pullUpView.closedCenter; 51 | pullUpView.handleView.frame = CGRectMake(0, 0, 320, 40); 52 | pullUpView.delegate = self; 53 | 54 | [self.view addSubview:pullUpView]; 55 | 56 | pullUpLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 4, 320, 20)]; 57 | pullUpLabel.textAlignment = UITextAlignmentCenter; 58 | pullUpLabel.backgroundColor = [UIColor clearColor]; 59 | pullUpLabel.textColor = [UIColor lightGrayColor]; 60 | pullUpLabel.text = @"Pull me up!"; 61 | 62 | [pullUpView addSubview:pullUpLabel]; 63 | 64 | label = [[UILabel alloc] initWithFrame:CGRectMake(0, 80, 320, 64)]; 65 | label.textAlignment = UITextAlignmentCenter; 66 | label.backgroundColor = [UIColor clearColor]; 67 | label.textColor = [UIColor whiteColor]; 68 | label.shadowColor = [UIColor blackColor]; 69 | label.shadowOffset = CGSizeMake(1, 1); 70 | label.text = @"I only go half-way up!"; 71 | 72 | [pullUpView addSubview:label]; 73 | 74 | pullDownView = [[StyledPullableView alloc] initWithFrame:CGRectMake(xOffset, 0, 320, 460)]; 75 | pullDownView.openedCenter = CGPointMake(160 + xOffset,230); 76 | pullDownView.closedCenter = CGPointMake(160 + xOffset, -200); 77 | pullDownView.center = pullDownView.closedCenter; 78 | 79 | [self.view addSubview:pullDownView]; 80 | 81 | label = [[UILabel alloc] initWithFrame:CGRectMake(0, 200, 320, 64)]; 82 | label.textAlignment = UITextAlignmentCenter; 83 | label.backgroundColor = [UIColor clearColor]; 84 | label.textColor = [UIColor whiteColor]; 85 | label.shadowColor = [UIColor blackColor]; 86 | label.shadowOffset = CGSizeMake(1, 1); 87 | label.text = @"Look at this beautiful linen texture!"; 88 | 89 | [pullDownView addSubview:label]; 90 | } 91 | 92 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 93 | { 94 | return UIInterfaceOrientationIsPortrait(interfaceOrientation); 95 | } 96 | 97 | - (void)pullableView:(PullableView *)pView didChangeState:(BOOL)opened { 98 | if (opened) { 99 | pullUpLabel.text = @"Now I'm open!"; 100 | } else { 101 | pullUpLabel.text = @"Now I'm closed, pull me up again!"; 102 | } 103 | } 104 | 105 | @end 106 | -------------------------------------------------------------------------------- /PullableView/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crocodella/PullableView/204507bbe37cb3936481a241619d9f7299a2dfbb/PullableView/background.png -------------------------------------------------------------------------------- /PullableView/background@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crocodella/PullableView/204507bbe37cb3936481a241619d9f7299a2dfbb/PullableView/background@2x.png -------------------------------------------------------------------------------- /PullableView/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /PullableView/en.lproj/ViewController_iPad.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1280 5 | 10K549 6 | 1938 7 | 1038.36 8 | 461.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 933 12 | 13 | 14 | IBProxyObject 15 | IBUIView 16 | IBUILabel 17 | 18 | 19 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 20 | 21 | 22 | PluginDependencyRecalculationVersion 23 | 24 | 25 | 26 | 27 | IBFilesOwner 28 | IBIPadFramework 29 | 30 | 31 | IBFirstResponder 32 | IBIPadFramework 33 | 34 | 35 | 36 | 274 37 | 38 | 39 | 40 | 292 41 | {{280, 407}, {186, 141}} 42 | 43 | 44 | NO 45 | YES 46 | 7 47 | NO 48 | IBIPadFramework 49 | This is your main content 50 | 51 | 1 52 | MCAwIDAAA 53 | 54 | 55 | 1 56 | 10 57 | 0 58 | 1 59 | 60 | 1 61 | 20 62 | 63 | 64 | Helvetica 65 | 20 66 | 16 67 | 68 | 69 | 70 | {{0, 20}, {768, 1004}} 71 | 72 | 73 | 74 | 3 75 | MQA 76 | 77 | 2 78 | 79 | 80 | 81 | 2 82 | 83 | IBIPadFramework 84 | 85 | 86 | 87 | 88 | 89 | 90 | view 91 | 92 | 93 | 94 | 3 95 | 96 | 97 | 98 | 99 | 100 | 0 101 | 102 | 103 | 104 | 105 | 106 | -1 107 | 108 | 109 | File's Owner 110 | 111 | 112 | -2 113 | 114 | 115 | 116 | 117 | 2 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 4 126 | 127 | 128 | 129 | 130 | 131 | 132 | ViewController 133 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 134 | UIResponder 135 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 136 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 137 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 138 | 139 | 140 | 141 | 142 | 143 | 4 144 | 145 | 146 | 147 | 148 | ViewController 149 | UIViewController 150 | 151 | IBProjectSource 152 | ./Classes/ViewController.h 153 | 154 | 155 | 156 | 157 | 0 158 | IBIPadFramework 159 | YES 160 | 3 161 | 933 162 | 163 | 164 | -------------------------------------------------------------------------------- /PullableView/en.lproj/ViewController_iPhone.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1280 5 | 10K549 6 | 1938 7 | 1038.36 8 | 461.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 933 12 | 13 | 14 | IBProxyObject 15 | IBUIView 16 | IBUILabel 17 | 18 | 19 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 20 | 21 | 22 | PluginDependencyRecalculationVersion 23 | 24 | 25 | 26 | 27 | IBFilesOwner 28 | IBCocoaTouchFramework 29 | 30 | 31 | IBFirstResponder 32 | IBCocoaTouchFramework 33 | 34 | 35 | 36 | 274 37 | 38 | 39 | 40 | 292 41 | {{69, 164}, {186, 141}} 42 | 43 | 44 | 45 | NO 46 | YES 47 | 7 48 | NO 49 | IBCocoaTouchFramework 50 | This is your main content 51 | 52 | 1 53 | MCAwIDAAA 54 | 55 | 56 | 1 57 | 10 58 | 0 59 | 1 60 | 61 | 1 62 | 20 63 | 64 | 65 | Helvetica 66 | 20 67 | 16 68 | 69 | 70 | 71 | {{0, 20}, {320, 460}} 72 | 73 | 74 | 75 | 76 | 3 77 | MQA 78 | 79 | NO 80 | 81 | IBCocoaTouchFramework 82 | 83 | 84 | 85 | 86 | 87 | 88 | view 89 | 90 | 91 | 92 | 7 93 | 94 | 95 | 96 | 97 | 98 | 0 99 | 100 | 101 | 102 | 103 | 104 | -1 105 | 106 | 107 | File's Owner 108 | 109 | 110 | -2 111 | 112 | 113 | 114 | 115 | 6 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 8 124 | 125 | 126 | 127 | 128 | 129 | 130 | ViewController 131 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 132 | UIResponder 133 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 134 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 135 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 136 | 137 | 138 | 139 | 140 | 141 | 8 142 | 143 | 144 | 145 | 146 | ViewController 147 | UIViewController 148 | 149 | IBProjectSource 150 | ./Classes/ViewController.h 151 | 152 | 153 | 154 | 155 | 0 156 | IBCocoaTouchFramework 157 | YES 158 | 3 159 | 933 160 | 161 | 162 | -------------------------------------------------------------------------------- /PullableView/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // PullableView 4 | // 5 | // Created by Fabio Rodella on 1/20/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | UIView subclass that implements pullable behaviour similar to the Notification Center in iOS 5. More information: http://www.crocodella.com.br/2012/01/a-pullable-view-implementation-like-notification-center/ --------------------------------------------------------------------------------