├── .gitignore ├── Demo ├── Classes │ ├── PSStoreButtonDemoAppDelegate.h │ ├── PSStoreButtonDemoAppDelegate.m │ ├── PSStoreButtonDemoViewController.h │ └── PSStoreButtonDemoViewController.m ├── MainWindow.xib ├── PSStoreButtonDemo-Info.plist ├── PSStoreButtonDemo.xcodeproj │ └── project.pbxproj ├── PSStoreButtonDemoViewController.xib ├── PSStoreButtonDemo_Prefix.pch └── main.m ├── PSStoreButton.h ├── PSStoreButton.m └── README.mdown /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | build/* 3 | *.pbxuser 4 | !default.pbxuser 5 | *.mode1v3 6 | !default.mode1v3 7 | *.mode2v3 8 | !default.mode2v3 9 | *.perspectivev3 10 | !default.perspectivev3 11 | *.xcworkspace 12 | !default.xcworkspace 13 | xcuserdata 14 | profile 15 | *.moved-aside 16 | 17 | # osx noise 18 | .DS_Store 19 | profile 20 | 21 | Development -------------------------------------------------------------------------------- /Demo/Classes/PSStoreButtonDemoAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // PSStoreButtonDemoAppDelegate.h 3 | // PSStoreButtonDemo 4 | // 5 | // Created by Peter Steinberger on 17.02.11. 6 | // Copyright 2011 Peter Steinberger. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class PSStoreButtonDemoViewController; 12 | 13 | @interface PSStoreButtonDemoAppDelegate : NSObject { 14 | UIWindow *window; 15 | PSStoreButtonDemoViewController *viewController; 16 | } 17 | 18 | @property (nonatomic, retain) IBOutlet UIWindow *window; 19 | @property (nonatomic, retain) IBOutlet PSStoreButtonDemoViewController *viewController; 20 | 21 | @end 22 | 23 | -------------------------------------------------------------------------------- /Demo/Classes/PSStoreButtonDemoAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // PSStoreButtonDemoAppDelegate.m 3 | // PSStoreButtonDemo 4 | // 5 | // Created by Peter Steinberger on 17.02.11. 6 | // Copyright 2011 Peter Steinberger. All rights reserved. 7 | // 8 | 9 | #import "PSStoreButtonDemoAppDelegate.h" 10 | #import "PSStoreButtonDemoViewController.h" 11 | 12 | @implementation PSStoreButtonDemoAppDelegate 13 | 14 | @synthesize window; 15 | @synthesize viewController; 16 | 17 | 18 | #pragma mark - 19 | #pragma mark Application lifecycle 20 | 21 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 22 | 23 | // Override point for customization after application launch. 24 | 25 | // Set the view controller as the window's root view controller and display. 26 | self.window.rootViewController = self.viewController; 27 | [self.window makeKeyAndVisible]; 28 | 29 | return YES; 30 | } 31 | 32 | 33 | - (void)applicationWillResignActive:(UIApplication *)application { 34 | /* 35 | 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. 36 | 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. 37 | */ 38 | } 39 | 40 | 41 | - (void)applicationDidEnterBackground:(UIApplication *)application { 42 | /* 43 | 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. 44 | If your application supports background execution, called instead of applicationWillTerminate: when the user quits. 45 | */ 46 | } 47 | 48 | 49 | - (void)applicationWillEnterForeground:(UIApplication *)application { 50 | /* 51 | Called as part of transition from the background to the inactive state: here you can undo many of the changes made on entering the background. 52 | */ 53 | } 54 | 55 | 56 | - (void)applicationDidBecomeActive:(UIApplication *)application { 57 | /* 58 | 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. 59 | */ 60 | } 61 | 62 | 63 | - (void)applicationWillTerminate:(UIApplication *)application { 64 | /* 65 | Called when the application is about to terminate. 66 | See also applicationDidEnterBackground:. 67 | */ 68 | } 69 | 70 | 71 | #pragma mark - 72 | #pragma mark Memory management 73 | 74 | - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { 75 | /* 76 | Free up as much memory as possible by purging cached data objects that can be recreated (or reloaded from disk) later. 77 | */ 78 | } 79 | 80 | 81 | - (void)dealloc { 82 | [viewController release]; 83 | [window release]; 84 | [super dealloc]; 85 | } 86 | 87 | 88 | @end 89 | -------------------------------------------------------------------------------- /Demo/Classes/PSStoreButtonDemoViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // PSStoreButtonDemoViewController.h 3 | // PSStoreButtonDemo 4 | // 5 | // Created by Peter Steinberger on 17.02.11. 6 | // Copyright 2011 Peter Steinberger. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "PSStoreButton.h" 11 | 12 | @interface PSStoreButtonDemoViewController : UIViewController { 13 | PSStoreButton *storeButton1; 14 | PSStoreButton *storeButton2; 15 | PSStoreButton *storeButton3; 16 | } 17 | 18 | @end 19 | 20 | -------------------------------------------------------------------------------- /Demo/Classes/PSStoreButtonDemoViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // PSStoreButtonDemoViewController.m 3 | // PSStoreButtonDemo 4 | // 5 | // Created by Peter Steinberger on 17.02.11. 6 | // Copyright 2011 Peter Steinberger. All rights reserved. 7 | // 8 | 9 | #import "PSStoreButtonDemoViewController.h" 10 | 11 | @implementation PSStoreButtonDemoViewController 12 | 13 | - (void)viewDidLoad { 14 | [super viewDidLoad]; 15 | 16 | storeButton1 = [[PSStoreButton storeButton] retain]; 17 | storeButton1.buttonDelegate = self; 18 | storeButton1.buttonData = [PSStoreButtonData dataWithLabel:@"3,99 $" colors:[PSStoreButton appStoreGreenColor] enabled:YES]; 19 | storeButton1.tag = 1; // mark button for delegate 20 | storeButton1.frame = CGRectMake(20, 100, 100, 25); 21 | [self.view addSubview:storeButton1]; 22 | 23 | storeButton2 = [[PSStoreButton storeButton] retain]; 24 | storeButton2.buttonDelegate = self; 25 | storeButton2.buttonData = [PSStoreButtonData dataWithLabel:@"9,99 $" colors:[PSStoreButton appStoreGreenColor] enabled:YES]; 26 | storeButton2.customPadding = CGPointMake(10, 10); 27 | storeButton2.frame = CGRectMake(0, 0, 100, 25); 28 | storeButton2.tag = 2; // mark button for delegate 29 | [self.view addSubview:storeButton2]; 30 | [storeButton2 alignToSuperview]; 31 | 32 | NSArray *customColor = [NSArray arrayWithObjects:(id) 33 | [UIColor redColor].CGColor, 34 | [UIColor orangeColor].CGColor, nil]; 35 | 36 | storeButton3 = [[PSStoreButton storeButton] retain]; 37 | storeButton3.buttonDelegate = self; 38 | storeButton3.buttonData = [PSStoreButtonData dataWithLabel:@"Custom" colors:customColor enabled:YES]; 39 | storeButton3.tag = 3; // mark button for delegate 40 | storeButton3.frame = CGRectMake(20, 200, 100, 25); 41 | [self.view addSubview:storeButton3]; 42 | } 43 | 44 | - (void)didReceiveMemoryWarning { 45 | // Releases the view if it doesn't have a superview. 46 | [super didReceiveMemoryWarning]; 47 | 48 | // Release any cached data, images, etc that aren't in use. 49 | } 50 | 51 | - (void)viewDidUnload { 52 | // Release any retained subviews of the main view. 53 | // e.g. self.myOutlet = nil; 54 | } 55 | 56 | 57 | - (void)dealloc { 58 | [storeButton1 release]; 59 | [storeButton2 release]; 60 | [storeButton3 release]; 61 | [super dealloc]; 62 | } 63 | 64 | - (void)resetButton1 { 65 | [storeButton1 setButtonData:[PSStoreButtonData dataWithLabel:@"3,99 $" colors:[PSStoreButton appStoreGreenColor] enabled:YES] animated:YES]; 66 | } 67 | 68 | // PSStoreButtonDelegate 69 | - (void)storeButtonFired:(PSStoreButton *)button { 70 | if(button.tag == 1 || button.tag == 2) { 71 | if ([button.buttonData.label hasSuffix:@"$"]) { 72 | [button setButtonData:[PSStoreButtonData dataWithLabel:@"BUY NOW" colors:[PSStoreButton appStoreGreenColor] enabled:YES] animated:YES]; 73 | }else if ([button.buttonData.label isEqualToString:@"BUY NOW"]) { 74 | [button setButtonData:[PSStoreButtonData dataWithLabel:@"INSTALLING" colors:[PSStoreButton appStoreGrayColor] enabled:NO] animated:YES]; 75 | [self performSelector:@selector(resetButton1) withObject:nil afterDelay:2.0]; 76 | } 77 | }else if (button.tag == 3) { 78 | if ([button.buttonData.label hasSuffix:@"Custom"]) { 79 | [button setButtonData:[PSStoreButtonData dataWithLabel:@"Max Width can be defined" colors:[PSStoreButton appStoreGreenColor] enabled:YES] animated:YES]; 80 | }else { 81 | [button setButtonData:[PSStoreButtonData dataWithLabel:@"Custom" colors:[PSStoreButton appStoreGrayColor] enabled:YES] animated:YES]; 82 | } 83 | } 84 | } 85 | 86 | @end 87 | -------------------------------------------------------------------------------- /Demo/MainWindow.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1024 5 | 10D571 6 | 786 7 | 1038.29 8 | 460.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 112 12 | 13 | 14 | YES 15 | 16 | 17 | 18 | YES 19 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 20 | 21 | 22 | YES 23 | 24 | YES 25 | 26 | 27 | YES 28 | 29 | 30 | 31 | YES 32 | 33 | IBFilesOwner 34 | IBCocoaTouchFramework 35 | 36 | 37 | IBFirstResponder 38 | IBCocoaTouchFramework 39 | 40 | 41 | IBCocoaTouchFramework 42 | 43 | 44 | PSStoreButtonDemoViewController 45 | 46 | 47 | 1 48 | 49 | IBCocoaTouchFramework 50 | NO 51 | 52 | 53 | 54 | 292 55 | {320, 480} 56 | 57 | 1 58 | MSAxIDEAA 59 | 60 | NO 61 | NO 62 | 63 | IBCocoaTouchFramework 64 | YES 65 | 66 | 67 | 68 | 69 | YES 70 | 71 | 72 | delegate 73 | 74 | 75 | 76 | 4 77 | 78 | 79 | 80 | viewController 81 | 82 | 83 | 84 | 11 85 | 86 | 87 | 88 | window 89 | 90 | 91 | 92 | 14 93 | 94 | 95 | 96 | 97 | YES 98 | 99 | 0 100 | 101 | 102 | 103 | 104 | 105 | -1 106 | 107 | 108 | File's Owner 109 | 110 | 111 | 3 112 | 113 | 114 | PSStoreButtonDemo App Delegate 115 | 116 | 117 | -2 118 | 119 | 120 | 121 | 122 | 10 123 | 124 | 125 | 126 | 127 | 12 128 | 129 | 130 | 131 | 132 | 133 | 134 | YES 135 | 136 | YES 137 | -1.CustomClassName 138 | -2.CustomClassName 139 | 10.CustomClassName 140 | 10.IBEditorWindowLastContentRect 141 | 10.IBPluginDependency 142 | 12.IBEditorWindowLastContentRect 143 | 12.IBPluginDependency 144 | 3.CustomClassName 145 | 3.IBPluginDependency 146 | 147 | 148 | YES 149 | UIApplication 150 | UIResponder 151 | PSStoreButtonDemoViewController 152 | {{234, 376}, {320, 480}} 153 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 154 | {{525, 346}, {320, 480}} 155 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 156 | PSStoreButtonDemoAppDelegate 157 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 158 | 159 | 160 | 161 | YES 162 | 163 | 164 | YES 165 | 166 | 167 | 168 | 169 | YES 170 | 171 | 172 | YES 173 | 174 | 175 | 176 | 15 177 | 178 | 179 | 180 | YES 181 | 182 | UIWindow 183 | UIView 184 | 185 | IBUserSource 186 | 187 | 188 | 189 | 190 | PSStoreButtonDemoAppDelegate 191 | NSObject 192 | 193 | YES 194 | 195 | YES 196 | viewController 197 | window 198 | 199 | 200 | YES 201 | PSStoreButtonDemoViewController 202 | UIWindow 203 | 204 | 205 | 206 | YES 207 | 208 | YES 209 | viewController 210 | window 211 | 212 | 213 | YES 214 | 215 | viewController 216 | PSStoreButtonDemoViewController 217 | 218 | 219 | window 220 | UIWindow 221 | 222 | 223 | 224 | 225 | IBProjectSource 226 | Classes/PSStoreButtonDemoAppDelegate.h 227 | 228 | 229 | 230 | PSStoreButtonDemoAppDelegate 231 | NSObject 232 | 233 | IBUserSource 234 | 235 | 236 | 237 | 238 | PSStoreButtonDemoViewController 239 | UIViewController 240 | 241 | IBProjectSource 242 | Classes/PSStoreButtonDemoViewController.h 243 | 244 | 245 | 246 | 247 | YES 248 | 249 | NSObject 250 | 251 | IBFrameworkSource 252 | Foundation.framework/Headers/NSError.h 253 | 254 | 255 | 256 | NSObject 257 | 258 | IBFrameworkSource 259 | Foundation.framework/Headers/NSFileManager.h 260 | 261 | 262 | 263 | NSObject 264 | 265 | IBFrameworkSource 266 | Foundation.framework/Headers/NSKeyValueCoding.h 267 | 268 | 269 | 270 | NSObject 271 | 272 | IBFrameworkSource 273 | Foundation.framework/Headers/NSKeyValueObserving.h 274 | 275 | 276 | 277 | NSObject 278 | 279 | IBFrameworkSource 280 | Foundation.framework/Headers/NSKeyedArchiver.h 281 | 282 | 283 | 284 | NSObject 285 | 286 | IBFrameworkSource 287 | Foundation.framework/Headers/NSObject.h 288 | 289 | 290 | 291 | NSObject 292 | 293 | IBFrameworkSource 294 | Foundation.framework/Headers/NSRunLoop.h 295 | 296 | 297 | 298 | NSObject 299 | 300 | IBFrameworkSource 301 | Foundation.framework/Headers/NSThread.h 302 | 303 | 304 | 305 | NSObject 306 | 307 | IBFrameworkSource 308 | Foundation.framework/Headers/NSURL.h 309 | 310 | 311 | 312 | NSObject 313 | 314 | IBFrameworkSource 315 | Foundation.framework/Headers/NSURLConnection.h 316 | 317 | 318 | 319 | NSObject 320 | 321 | IBFrameworkSource 322 | UIKit.framework/Headers/UIAccessibility.h 323 | 324 | 325 | 326 | NSObject 327 | 328 | IBFrameworkSource 329 | UIKit.framework/Headers/UINibLoading.h 330 | 331 | 332 | 333 | NSObject 334 | 335 | IBFrameworkSource 336 | UIKit.framework/Headers/UIResponder.h 337 | 338 | 339 | 340 | UIApplication 341 | UIResponder 342 | 343 | IBFrameworkSource 344 | UIKit.framework/Headers/UIApplication.h 345 | 346 | 347 | 348 | UIResponder 349 | NSObject 350 | 351 | 352 | 353 | UISearchBar 354 | UIView 355 | 356 | IBFrameworkSource 357 | UIKit.framework/Headers/UISearchBar.h 358 | 359 | 360 | 361 | UISearchDisplayController 362 | NSObject 363 | 364 | IBFrameworkSource 365 | UIKit.framework/Headers/UISearchDisplayController.h 366 | 367 | 368 | 369 | UIView 370 | 371 | IBFrameworkSource 372 | UIKit.framework/Headers/UITextField.h 373 | 374 | 375 | 376 | UIView 377 | UIResponder 378 | 379 | IBFrameworkSource 380 | UIKit.framework/Headers/UIView.h 381 | 382 | 383 | 384 | UIViewController 385 | 386 | IBFrameworkSource 387 | UIKit.framework/Headers/UINavigationController.h 388 | 389 | 390 | 391 | UIViewController 392 | 393 | IBFrameworkSource 394 | UIKit.framework/Headers/UIPopoverController.h 395 | 396 | 397 | 398 | UIViewController 399 | 400 | IBFrameworkSource 401 | UIKit.framework/Headers/UISplitViewController.h 402 | 403 | 404 | 405 | UIViewController 406 | 407 | IBFrameworkSource 408 | UIKit.framework/Headers/UITabBarController.h 409 | 410 | 411 | 412 | UIViewController 413 | UIResponder 414 | 415 | IBFrameworkSource 416 | UIKit.framework/Headers/UIViewController.h 417 | 418 | 419 | 420 | UIWindow 421 | UIView 422 | 423 | IBFrameworkSource 424 | UIKit.framework/Headers/UIWindow.h 425 | 426 | 427 | 428 | 429 | 0 430 | IBCocoaTouchFramework 431 | 432 | com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS 433 | 434 | 435 | 436 | com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 437 | 438 | 439 | YES 440 | PSStoreButtonDemo.xcodeproj 441 | 3 442 | 112 443 | 444 | 445 | -------------------------------------------------------------------------------- /Demo/PSStoreButtonDemo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFile 12 | 13 | CFBundleIdentifier 14 | com.yourcompany.${PRODUCT_NAME:rfc1034identifier} 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | ${PRODUCT_NAME} 19 | CFBundlePackageType 20 | APPL 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | NSMainNibFile 28 | MainWindow 29 | 30 | 31 | -------------------------------------------------------------------------------- /Demo/PSStoreButtonDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1D3623260D0F684500981E51 /* PSStoreButtonDemoAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* PSStoreButtonDemoAppDelegate.m */; }; 11 | 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; 12 | 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; 13 | 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; 14 | 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765A40DF7441C002DB57D /* CoreGraphics.framework */; }; 15 | 2899E5220DE3E06400AC0155 /* PSStoreButtonDemoViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2899E5210DE3E06400AC0155 /* PSStoreButtonDemoViewController.xib */; }; 16 | 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; 17 | 28D7ACF80DDB3853001CB0EB /* PSStoreButtonDemoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28D7ACF70DDB3853001CB0EB /* PSStoreButtonDemoViewController.m */; }; 18 | 78DA460D130DB33500D1585D /* PSStoreButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 78DA460C130DB33500D1585D /* PSStoreButton.m */; }; 19 | 78DA461F130DB58F00D1585D /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 78DA461E130DB58F00D1585D /* QuartzCore.framework */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXFileReference section */ 23 | 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 24 | 1D3623240D0F684500981E51 /* PSStoreButtonDemoAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSStoreButtonDemoAppDelegate.h; sourceTree = ""; }; 25 | 1D3623250D0F684500981E51 /* PSStoreButtonDemoAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSStoreButtonDemoAppDelegate.m; sourceTree = ""; }; 26 | 1D6058910D05DD3D006BFB54 /* PSStoreButtonDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PSStoreButtonDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 28 | 288765A40DF7441C002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 29 | 2899E5210DE3E06400AC0155 /* PSStoreButtonDemoViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PSStoreButtonDemoViewController.xib; sourceTree = ""; }; 30 | 28AD733E0D9D9553002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; 31 | 28D7ACF60DDB3853001CB0EB /* PSStoreButtonDemoViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSStoreButtonDemoViewController.h; sourceTree = ""; }; 32 | 28D7ACF70DDB3853001CB0EB /* PSStoreButtonDemoViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSStoreButtonDemoViewController.m; sourceTree = ""; }; 33 | 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 34 | 32CA4F630368D1EE00C91783 /* PSStoreButtonDemo_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSStoreButtonDemo_Prefix.pch; sourceTree = ""; }; 35 | 78DA460B130DB33500D1585D /* PSStoreButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PSStoreButton.h; path = ../PSStoreButton.h; sourceTree = SOURCE_ROOT; }; 36 | 78DA460C130DB33500D1585D /* PSStoreButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PSStoreButton.m; path = ../PSStoreButton.m; sourceTree = SOURCE_ROOT; }; 37 | 78DA461E130DB58F00D1585D /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 38 | 8D1107310486CEB800E47090 /* PSStoreButtonDemo-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "PSStoreButtonDemo-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = ""; }; 39 | /* End PBXFileReference section */ 40 | 41 | /* Begin PBXFrameworksBuildPhase section */ 42 | 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { 43 | isa = PBXFrameworksBuildPhase; 44 | buildActionMask = 2147483647; 45 | files = ( 46 | 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, 47 | 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, 48 | 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */, 49 | 78DA461F130DB58F00D1585D /* QuartzCore.framework in Frameworks */, 50 | ); 51 | runOnlyForDeploymentPostprocessing = 0; 52 | }; 53 | /* End PBXFrameworksBuildPhase section */ 54 | 55 | /* Begin PBXGroup section */ 56 | 080E96DDFE201D6D7F000001 /* Classes */ = { 57 | isa = PBXGroup; 58 | children = ( 59 | 78DA4609130DB32A00D1585D /* PSStoreButton */, 60 | 1D3623240D0F684500981E51 /* PSStoreButtonDemoAppDelegate.h */, 61 | 1D3623250D0F684500981E51 /* PSStoreButtonDemoAppDelegate.m */, 62 | 28D7ACF60DDB3853001CB0EB /* PSStoreButtonDemoViewController.h */, 63 | 28D7ACF70DDB3853001CB0EB /* PSStoreButtonDemoViewController.m */, 64 | ); 65 | path = Classes; 66 | sourceTree = ""; 67 | }; 68 | 19C28FACFE9D520D11CA2CBB /* Products */ = { 69 | isa = PBXGroup; 70 | children = ( 71 | 1D6058910D05DD3D006BFB54 /* PSStoreButtonDemo.app */, 72 | ); 73 | name = Products; 74 | sourceTree = ""; 75 | }; 76 | 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { 77 | isa = PBXGroup; 78 | children = ( 79 | 080E96DDFE201D6D7F000001 /* Classes */, 80 | 29B97315FDCFA39411CA2CEA /* Other Sources */, 81 | 29B97317FDCFA39411CA2CEA /* Resources */, 82 | 29B97323FDCFA39411CA2CEA /* Frameworks */, 83 | 19C28FACFE9D520D11CA2CBB /* Products */, 84 | ); 85 | name = CustomTemplate; 86 | sourceTree = ""; 87 | }; 88 | 29B97315FDCFA39411CA2CEA /* Other Sources */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | 32CA4F630368D1EE00C91783 /* PSStoreButtonDemo_Prefix.pch */, 92 | 29B97316FDCFA39411CA2CEA /* main.m */, 93 | ); 94 | name = "Other Sources"; 95 | sourceTree = ""; 96 | }; 97 | 29B97317FDCFA39411CA2CEA /* Resources */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 2899E5210DE3E06400AC0155 /* PSStoreButtonDemoViewController.xib */, 101 | 28AD733E0D9D9553002E5188 /* MainWindow.xib */, 102 | 8D1107310486CEB800E47090 /* PSStoreButtonDemo-Info.plist */, 103 | ); 104 | name = Resources; 105 | sourceTree = ""; 106 | }; 107 | 29B97323FDCFA39411CA2CEA /* Frameworks */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, 111 | 1D30AB110D05D00D00671497 /* Foundation.framework */, 112 | 288765A40DF7441C002DB57D /* CoreGraphics.framework */, 113 | 78DA461E130DB58F00D1585D /* QuartzCore.framework */, 114 | ); 115 | name = Frameworks; 116 | sourceTree = ""; 117 | }; 118 | 78DA4609130DB32A00D1585D /* PSStoreButton */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 78DA460B130DB33500D1585D /* PSStoreButton.h */, 122 | 78DA460C130DB33500D1585D /* PSStoreButton.m */, 123 | ); 124 | name = PSStoreButton; 125 | sourceTree = ""; 126 | }; 127 | /* End PBXGroup section */ 128 | 129 | /* Begin PBXNativeTarget section */ 130 | 1D6058900D05DD3D006BFB54 /* PSStoreButtonDemo */ = { 131 | isa = PBXNativeTarget; 132 | buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "PSStoreButtonDemo" */; 133 | buildPhases = ( 134 | 1D60588D0D05DD3D006BFB54 /* Resources */, 135 | 1D60588E0D05DD3D006BFB54 /* Sources */, 136 | 1D60588F0D05DD3D006BFB54 /* Frameworks */, 137 | ); 138 | buildRules = ( 139 | ); 140 | dependencies = ( 141 | ); 142 | name = PSStoreButtonDemo; 143 | productName = PSStoreButtonDemo; 144 | productReference = 1D6058910D05DD3D006BFB54 /* PSStoreButtonDemo.app */; 145 | productType = "com.apple.product-type.application"; 146 | }; 147 | /* End PBXNativeTarget section */ 148 | 149 | /* Begin PBXProject section */ 150 | 29B97313FDCFA39411CA2CEA /* Project object */ = { 151 | isa = PBXProject; 152 | buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "PSStoreButtonDemo" */; 153 | compatibilityVersion = "Xcode 3.2"; 154 | developmentRegion = English; 155 | hasScannedForEncodings = 1; 156 | knownRegions = ( 157 | English, 158 | Japanese, 159 | French, 160 | German, 161 | ); 162 | mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; 163 | projectDirPath = ""; 164 | projectRoot = ""; 165 | targets = ( 166 | 1D6058900D05DD3D006BFB54 /* PSStoreButtonDemo */, 167 | ); 168 | }; 169 | /* End PBXProject section */ 170 | 171 | /* Begin PBXResourcesBuildPhase section */ 172 | 1D60588D0D05DD3D006BFB54 /* Resources */ = { 173 | isa = PBXResourcesBuildPhase; 174 | buildActionMask = 2147483647; 175 | files = ( 176 | 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */, 177 | 2899E5220DE3E06400AC0155 /* PSStoreButtonDemoViewController.xib in Resources */, 178 | ); 179 | runOnlyForDeploymentPostprocessing = 0; 180 | }; 181 | /* End PBXResourcesBuildPhase section */ 182 | 183 | /* Begin PBXSourcesBuildPhase section */ 184 | 1D60588E0D05DD3D006BFB54 /* Sources */ = { 185 | isa = PBXSourcesBuildPhase; 186 | buildActionMask = 2147483647; 187 | files = ( 188 | 1D60589B0D05DD56006BFB54 /* main.m in Sources */, 189 | 1D3623260D0F684500981E51 /* PSStoreButtonDemoAppDelegate.m in Sources */, 190 | 28D7ACF80DDB3853001CB0EB /* PSStoreButtonDemoViewController.m in Sources */, 191 | 78DA460D130DB33500D1585D /* PSStoreButton.m in Sources */, 192 | ); 193 | runOnlyForDeploymentPostprocessing = 0; 194 | }; 195 | /* End PBXSourcesBuildPhase section */ 196 | 197 | /* Begin XCBuildConfiguration section */ 198 | 1D6058940D05DD3E006BFB54 /* Debug */ = { 199 | isa = XCBuildConfiguration; 200 | buildSettings = { 201 | ALWAYS_SEARCH_USER_PATHS = NO; 202 | COPY_PHASE_STRIP = NO; 203 | GCC_DYNAMIC_NO_PIC = NO; 204 | GCC_OPTIMIZATION_LEVEL = 0; 205 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 206 | GCC_PREFIX_HEADER = PSStoreButtonDemo_Prefix.pch; 207 | INFOPLIST_FILE = "PSStoreButtonDemo-Info.plist"; 208 | PRODUCT_NAME = PSStoreButtonDemo; 209 | }; 210 | name = Debug; 211 | }; 212 | 1D6058950D05DD3E006BFB54 /* Release */ = { 213 | isa = XCBuildConfiguration; 214 | buildSettings = { 215 | ALWAYS_SEARCH_USER_PATHS = NO; 216 | COPY_PHASE_STRIP = YES; 217 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 218 | GCC_PREFIX_HEADER = PSStoreButtonDemo_Prefix.pch; 219 | INFOPLIST_FILE = "PSStoreButtonDemo-Info.plist"; 220 | PRODUCT_NAME = PSStoreButtonDemo; 221 | VALIDATE_PRODUCT = YES; 222 | }; 223 | name = Release; 224 | }; 225 | C01FCF4F08A954540054247B /* Debug */ = { 226 | isa = XCBuildConfiguration; 227 | buildSettings = { 228 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 229 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 230 | GCC_C_LANGUAGE_STANDARD = c99; 231 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 232 | GCC_WARN_UNUSED_VARIABLE = YES; 233 | PREBINDING = NO; 234 | SDKROOT = iphoneos; 235 | }; 236 | name = Debug; 237 | }; 238 | C01FCF5008A954540054247B /* Release */ = { 239 | isa = XCBuildConfiguration; 240 | buildSettings = { 241 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 242 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 243 | GCC_C_LANGUAGE_STANDARD = c99; 244 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 245 | GCC_WARN_UNUSED_VARIABLE = YES; 246 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 247 | PREBINDING = NO; 248 | SDKROOT = iphoneos; 249 | }; 250 | name = Release; 251 | }; 252 | /* End XCBuildConfiguration section */ 253 | 254 | /* Begin XCConfigurationList section */ 255 | 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "PSStoreButtonDemo" */ = { 256 | isa = XCConfigurationList; 257 | buildConfigurations = ( 258 | 1D6058940D05DD3E006BFB54 /* Debug */, 259 | 1D6058950D05DD3E006BFB54 /* Release */, 260 | ); 261 | defaultConfigurationIsVisible = 0; 262 | defaultConfigurationName = Release; 263 | }; 264 | C01FCF4E08A954540054247B /* Build configuration list for PBXProject "PSStoreButtonDemo" */ = { 265 | isa = XCConfigurationList; 266 | buildConfigurations = ( 267 | C01FCF4F08A954540054247B /* Debug */, 268 | C01FCF5008A954540054247B /* Release */, 269 | ); 270 | defaultConfigurationIsVisible = 0; 271 | defaultConfigurationName = Release; 272 | }; 273 | /* End XCConfigurationList section */ 274 | }; 275 | rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; 276 | } 277 | -------------------------------------------------------------------------------- /Demo/PSStoreButtonDemoViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 800 5 | 10C540 6 | 759 7 | 1038.25 8 | 458.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 77 12 | 13 | 14 | YES 15 | 16 | 17 | 18 | YES 19 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 20 | 21 | 22 | YES 23 | 24 | YES 25 | 26 | 27 | YES 28 | 29 | 30 | 31 | YES 32 | 33 | IBFilesOwner 34 | IBCocoaTouchFramework 35 | 36 | 37 | IBFirstResponder 38 | IBCocoaTouchFramework 39 | 40 | 41 | 42 | 274 43 | {320, 460} 44 | 45 | 46 | 3 47 | MC43NQA 48 | 49 | 2 50 | 51 | 52 | NO 53 | 54 | IBCocoaTouchFramework 55 | 56 | 57 | 58 | 59 | YES 60 | 61 | 62 | view 63 | 64 | 65 | 66 | 7 67 | 68 | 69 | 70 | 71 | YES 72 | 73 | 0 74 | 75 | 76 | 77 | 78 | 79 | -1 80 | 81 | 82 | File's Owner 83 | 84 | 85 | -2 86 | 87 | 88 | 89 | 90 | 6 91 | 92 | 93 | 94 | 95 | 96 | 97 | YES 98 | 99 | YES 100 | -1.CustomClassName 101 | -2.CustomClassName 102 | 6.IBEditorWindowLastContentRect 103 | 6.IBPluginDependency 104 | 105 | 106 | YES 107 | PSStoreButtonDemoViewController 108 | UIResponder 109 | {{239, 654}, {320, 480}} 110 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 111 | 112 | 113 | 114 | YES 115 | 116 | 117 | YES 118 | 119 | 120 | 121 | 122 | YES 123 | 124 | 125 | YES 126 | 127 | 128 | 129 | 7 130 | 131 | 132 | 133 | YES 134 | 135 | PSStoreButtonDemoViewController 136 | UIViewController 137 | 138 | IBProjectSource 139 | Classes/PSStoreButtonDemoViewController.h 140 | 141 | 142 | 143 | 144 | 0 145 | IBCocoaTouchFramework 146 | 147 | com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 148 | 149 | 150 | YES 151 | PSStoreButtonDemo.xcodeproj 152 | 3 153 | 77 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /Demo/PSStoreButtonDemo_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'PSStoreButtonDemo' target in the 'PSStoreButtonDemo' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #import 8 | #endif 9 | -------------------------------------------------------------------------------- /Demo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // PSStoreButtonDemo 4 | // 5 | // Created by Peter Steinberger on 17.02.11. 6 | // Copyright 2011 Peter Steinberger. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) { 12 | 13 | NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 14 | int retVal = UIApplicationMain(argc, argv, nil, nil); 15 | [pool release]; 16 | return retVal; 17 | } 18 | -------------------------------------------------------------------------------- /PSStoreButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // PSStoreButton.h 3 | // 4 | // Created by Peter Steinberger on 09.01.11. 5 | // Copyright 2011 Peter Steinberger. All rights reserved. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | 25 | #import 26 | 27 | // defines a button action set (data container) 28 | @interface PSStoreButtonData : NSObject { 29 | CGPoint customPadding_; 30 | NSString *label_; 31 | NSArray *colors_; 32 | BOOL enabled_; 33 | } 34 | 35 | + (id)dataWithLabel:(NSString*)aLabel colors:(NSArray*)aColors enabled:(BOOL)flag; 36 | 37 | @property (nonatomic, copy) NSString *label; 38 | @property (nonatomic, retain) NSArray *colors; 39 | @property (nonatomic, assign, getter=isEnabled) BOOL enabled; 40 | 41 | @end 42 | 43 | 44 | @class PSStoreButton; 45 | @protocol PSStoreButtonDelegate 46 | - (void)storeButtonFired:(PSStoreButton *)button; 47 | @end 48 | 49 | 50 | // Simulate the Paymeny-Button from the AppStore 51 | // The interface is flexible, so there is now fixed order 52 | @interface PSStoreButton : UIButton { 53 | PSStoreButtonData *buttonData_; 54 | id buttonDelegate_; 55 | 56 | CAGradientLayer *gradient_; 57 | CGPoint customPadding_; 58 | } 59 | 60 | + (PSStoreButton *)storeButton; 61 | 62 | - (id)initWithFrame:(CGRect)frame; 63 | 64 | // init with padding helper 65 | - (id)initWithPadding:(CGPoint)padding; 66 | 67 | // action delegate 68 | @property (nonatomic, assign) id buttonDelegate; 69 | 70 | // change the button layer 71 | @property (nonatomic, retain) PSStoreButtonData *buttonData; 72 | - (void)setButtonData:(PSStoreButtonData *)aButtonData animated:(BOOL)animated; 73 | 74 | // align helper 75 | @property (nonatomic, assign) CGPoint customPadding; 76 | - (void)alignToSuperview; 77 | 78 | // helpers to mimic an AppStore button 79 | + (NSArray *)appStoreGreenColor; 80 | + (NSArray *)appStoreBlueColor; 81 | + (NSArray *)appStoreGrayColor; 82 | 83 | @end 84 | -------------------------------------------------------------------------------- /PSStoreButton.m: -------------------------------------------------------------------------------- 1 | // 2 | // PSStoreButton.m 3 | // 4 | // Created by Peter Steinberger on 09.01.11. 5 | // Copyright 2011 Peter Steinberger. All rights reserved. 6 | // 7 | // This code was inspired by https://github.com/dhmspector/ZIStoreButton 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | 27 | #import "PSStoreButton.h" 28 | 29 | #ifdef DEBUG 30 | #define PSLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); 31 | #else 32 | #define PSLog(...) 33 | #endif 34 | 35 | #define RGBCOLOR(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1] 36 | #define PS_MIN_HEIGHT 25.0f 37 | #define PS_MAX_WIDTH 220.0f 38 | #define PS_PADDING 12.0f 39 | #define kDefaultButtonAnimationTime 0.25f 40 | 41 | @implementation PSStoreButtonData 42 | 43 | @synthesize label = label_; 44 | @synthesize colors = colors_; 45 | @synthesize enabled = enabled_; 46 | 47 | /////////////////////////////////////////////////////////////////////////////////////////////////// 48 | #pragma mark - 49 | #pragma mark NSObject 50 | 51 | - (id)initWithLabel:(NSString*)aLabel colors:(NSArray*)aColors enabled:(BOOL)flag { 52 | if ((self = [super init])) { 53 | self.label = aLabel; 54 | self.colors = aColors; 55 | self.enabled = flag; 56 | } 57 | return self; 58 | } 59 | 60 | + (id)dataWithLabel:(NSString*)aLabel colors:(NSArray*)aColors enabled:(BOOL)flag { 61 | return [[[[self class] alloc] initWithLabel:aLabel colors:aColors enabled:flag] autorelease]; 62 | } 63 | 64 | - (void)dealloc { 65 | [label_ release]; 66 | [colors_ release]; 67 | 68 | [super dealloc]; 69 | } 70 | @end 71 | 72 | 73 | @interface PSStoreButton () 74 | // call when buttonData was updated 75 | - (void)updateButtonAnimated:(BOOL)animated; 76 | @end 77 | 78 | 79 | @implementation PSStoreButton 80 | 81 | @synthesize buttonData = buttonData_; 82 | @synthesize buttonDelegate = buttonDelegate_; 83 | @synthesize customPadding = customPadding_; 84 | 85 | /////////////////////////////////////////////////////////////////////////////////////////////////// 86 | #pragma mark - 87 | #pragma mark static 88 | 89 | 90 | + (PSStoreButton *)storeButton { 91 | return [[[self class] alloc] initWithFrame:CGRectMake(0, 0, 200, 35)]; 92 | } 93 | 94 | /////////////////////////////////////////////////////////////////////////////////////////////////// 95 | #pragma mark - 96 | #pragma mark private 97 | 98 | - (void)touchedUpOutside:(id)sender { 99 | PSLog(@"touched outside..."); 100 | } 101 | 102 | - (void)buttonPressed:(id)sender { 103 | PSLog(@"calling delegate:storeButtonFired for %@", sender); 104 | [buttonDelegate_ storeButtonFired:self]; 105 | } 106 | 107 | - (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { 108 | // show text again, but only if animation did finish (or else another animation is on the way) 109 | if ([finished boolValue]) { 110 | [self setTitle:self.buttonData.label forState:UIControlStateNormal]; 111 | } 112 | } 113 | 114 | - (void)updateButtonAnimated:(BOOL)animated { 115 | if (animated) { 116 | // hide text, then start animation 117 | [self setTitle:@"" forState:UIControlStateNormal]; 118 | [UIView beginAnimations:@"storeButtonUpdate" context:nil]; 119 | [UIView setAnimationDuration:kDefaultButtonAnimationTime]; 120 | [UIView setAnimationDelegate:self]; 121 | [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)]; 122 | }else { 123 | [self setTitle:self.buttonData.label forState:UIControlStateNormal]; 124 | } 125 | 126 | self.enabled = self.buttonData.isEnabled; 127 | gradient_.colors = self.buttonData.colors; 128 | 129 | // show white or gray text, depending on the state 130 | if (self.buttonData.isEnabled) { 131 | [self setTitleShadowColor:[UIColor colorWithWhite:0.200 alpha:1.000] forState:UIControlStateNormal]; 132 | [self.titleLabel setShadowOffset:CGSizeMake(0.0, -0.6)]; 133 | [self setTitleColor:[UIColor colorWithWhite:1.0 alpha:1.000] forState:UIControlStateNormal]; 134 | }else { 135 | [self.titleLabel setShadowOffset:CGSizeMake(0.0, 0.0)]; 136 | [self setTitleColor:RGBCOLOR(148,150,151) forState:UIControlStateNormal]; 137 | } 138 | 139 | // calculate optimal new size 140 | CGSize sizeThatFits = [self sizeThatFits:CGSizeZero]; 141 | 142 | // move sublayer (can't be animated explcitely) 143 | for (CALayer *aLayer in self.layer.sublayers) { 144 | [CATransaction begin]; 145 | 146 | if (animated) { 147 | [CATransaction setAnimationDuration:kDefaultButtonAnimationTime]; 148 | [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]]; 149 | }else { 150 | // frame is calculated and explicitely animated. so we absolutely need kCATransactionDisableActions 151 | [CATransaction setValue:[NSNumber numberWithBool:YES] forKey:kCATransactionDisableActions]; 152 | } 153 | 154 | CGRect newFrame = aLayer.frame; 155 | newFrame.size.width = sizeThatFits.width; 156 | aLayer.frame = newFrame; 157 | 158 | [CATransaction commit]; 159 | } 160 | 161 | // set outer frame changes 162 | self.titleEdgeInsets = UIEdgeInsetsMake(2.0, self.titleEdgeInsets.left, 0.0, 0.0); 163 | CGRect cr = self.frame; 164 | if (!CGPointEqualToPoint(self.customPadding, CGPointZero)) { 165 | cr.origin.y = customPadding_.y; 166 | cr.origin.x = self.superview.frame.size.width - sizeThatFits.width - customPadding_.x * 2; 167 | } 168 | cr.size.width = sizeThatFits.width; 169 | self.frame = cr; 170 | 171 | if (animated) { 172 | [UIView commitAnimations]; 173 | } 174 | } 175 | 176 | - (void)alignToSuperview { 177 | [self sizeToFit]; 178 | CGRect cr = self.frame; 179 | cr.origin.y = customPadding_.y; 180 | cr.origin.x = self.superview.frame.size.width - cr.size.width - customPadding_.x * 2; 181 | self.frame = cr; 182 | } 183 | 184 | /////////////////////////////////////////////////////////////////////////////////////////////////// 185 | #pragma mark - 186 | #pragma mark NSObject 187 | 188 | - (id)initWithFrame:(CGRect)frame { 189 | if ((self = [super initWithFrame:frame])) { 190 | self.customPadding = CGPointZero; 191 | self.layer.needsDisplayOnBoundsChange = YES; 192 | 193 | // setup title label 194 | [self.titleLabel setFont:[UIFont boldSystemFontOfSize:13.0]]; 195 | 196 | // register for touch events 197 | [self addTarget:self action:@selector(touchedUpOutside:) forControlEvents:UIControlEventTouchUpOutside]; 198 | [self addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside]; 199 | 200 | // border layers for more sex! 201 | CAGradientLayer *bevelLayer = [CAGradientLayer layer]; 202 | bevelLayer.colors = [NSArray arrayWithObjects:(id)[[UIColor colorWithWhite:0.4 alpha:1.0] CGColor], [[UIColor whiteColor] CGColor], nil]; 203 | bevelLayer.frame = CGRectMake(0.0, 0.0, CGRectGetWidth(frame), CGRectGetHeight(frame)); 204 | bevelLayer.cornerRadius = 2.5; 205 | bevelLayer.needsDisplayOnBoundsChange = YES; 206 | [self.layer addSublayer:bevelLayer]; 207 | 208 | CAGradientLayer *topBorderLayer = [CAGradientLayer layer]; 209 | topBorderLayer.colors = [NSArray arrayWithObjects:(id)[[UIColor darkGrayColor] CGColor], [[UIColor lightGrayColor] CGColor], nil]; 210 | topBorderLayer.frame = CGRectMake(0.5, 0.5, CGRectGetWidth(frame) - 1.0, CGRectGetHeight(frame) - 1.0); 211 | topBorderLayer.cornerRadius = 2.6; 212 | topBorderLayer.needsDisplayOnBoundsChange = YES; 213 | [self.layer addSublayer:topBorderLayer]; 214 | 215 | // main gradient layer 216 | gradient_ = [[CAGradientLayer layer] retain]; 217 | gradient_.locations = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0], [NSNumber numberWithFloat:1.0], nil];//[NSNumber numberWithFloat:0.500], [NSNumber numberWithFloat:0.5001], 218 | gradient_.frame = CGRectMake(0.75, 0.75, CGRectGetWidth(frame) - 1.5, CGRectGetHeight(frame) - 1.5); 219 | gradient_.cornerRadius = 2.5; 220 | gradient_.needsDisplayOnBoundsChange = YES; 221 | [self.layer addSublayer:gradient_]; 222 | [self bringSubviewToFront:self.titleLabel]; 223 | } 224 | return self; 225 | } 226 | 227 | - (id)initWithPadding:(CGPoint)padding { 228 | if ((self = [self initWithFrame:CGRectMake(0, 0, 40, PS_MIN_HEIGHT)])) { 229 | customPadding_ = padding; 230 | } 231 | return self; 232 | } 233 | 234 | - (void)dealloc { 235 | [buttonData_ release]; 236 | [gradient_ release]; 237 | 238 | [super dealloc]; 239 | } 240 | 241 | /////////////////////////////////////////////////////////////////////////////////////////////////// 242 | #pragma mark - 243 | #pragma mark UIView 244 | 245 | - (CGSize)sizeThatFits:(CGSize)size { 246 | CGSize constr = (CGSize){.height = self.frame.size.height, .width = PS_MAX_WIDTH}; 247 | CGSize newSize = [self.buttonData.label sizeWithFont:self.titleLabel.font constrainedToSize:constr lineBreakMode:UILineBreakModeMiddleTruncation]; 248 | CGFloat newWidth = newSize.width + (PS_PADDING * 2); 249 | CGFloat newHeight = PS_MIN_HEIGHT > newSize.height ? PS_MIN_HEIGHT : newSize.height; 250 | 251 | CGSize sizeThatFits = CGSizeMake(newWidth, newHeight); 252 | return sizeThatFits; 253 | } 254 | 255 | - (void)setFrame:(CGRect)aRect { 256 | [super setFrame:aRect]; 257 | 258 | // copy frame changes to sublayers 259 | for (CALayer *aLayer in self.layer.sublayers) { 260 | CGRect rect = aLayer.frame; 261 | rect.size.width = self.frame.size.width; 262 | rect.size.height = self.frame.size.height; 263 | aLayer.frame = rect; 264 | [aLayer layoutIfNeeded]; 265 | } 266 | } 267 | 268 | /////////////////////////////////////////////////////////////////////////////////////////////////// 269 | #pragma mark - 270 | #pragma mark Properties 271 | 272 | - (void)setButtonData:(PSStoreButtonData *)aButtonData { 273 | [self setButtonData:aButtonData animated:NO]; 274 | } 275 | 276 | - (void)setButtonData:(PSStoreButtonData *)aButtonData animated:(BOOL)animated { 277 | if (buttonData_ != aButtonData) { 278 | [buttonData_ release]; 279 | buttonData_ = [aButtonData retain]; 280 | } 281 | 282 | [self updateButtonAnimated:animated]; 283 | } 284 | 285 | /////////////////////////////////////////////////////////////////////////////////////////////////// 286 | #pragma mark - 287 | #pragma mark Static 288 | 289 | + (NSArray *)appStoreGreenColor { 290 | return [NSArray arrayWithObjects:(id) 291 | [UIColor colorWithRed:0.482 green:0.674 blue:0.406 alpha:1.000].CGColor, 292 | [UIColor colorWithRed:0.299 green:0.606 blue:0.163 alpha:1.000].CGColor, nil]; 293 | } 294 | 295 | + (NSArray *)appStoreBlueColor { 296 | return [NSArray arrayWithObjects:(id) 297 | [UIColor colorWithRed:0.306 green:0.380 blue:0.547 alpha:1.000].CGColor, 298 | [UIColor colorWithRed:0.129 green:0.220 blue:0.452 alpha:1.000].CGColor, nil]; 299 | } 300 | 301 | + (NSArray *)appStoreGrayColor { 302 | return [NSArray arrayWithObjects:(id) 303 | RGBCOLOR(187,189,191).CGColor, 304 | RGBCOLOR(210,210,210).CGColor, nil]; 305 | } 306 | 307 | @end 308 | -------------------------------------------------------------------------------- /README.mdown: -------------------------------------------------------------------------------- 1 | Flexible reimplementation of the iOS AppStore Button. 2 | 3 | No images are used - styling is done with a sublcassed UIButton and Layers. You can choose the color, default colors for AppStoreGreen, Blue and Gray are setup. 4 | 5 | The Button can be set to align right, so you get this right-fixed expansion effect from the AppStore (customPadding) 6 | 7 | Works with iOS3 and up. 8 | 9 | ![Demo](https://img.skitch.com/20110221-c4ck9xgtaqcs1xf2m8wuahargc.jpg "Demo") 10 | 11 | MIT License because I love you. 12 | 13 | http://petersteinberger.com --------------------------------------------------------------------------------