├── SWCrawlViewExample ├── SWCrawlViewExample │ ├── SWCrawlView │ │ ├── Assets │ │ │ ├── Images │ │ │ │ ├── mask.png │ │ │ │ └── starBg.png │ │ │ └── Fonts │ │ │ │ ├── Starjedi.ttf │ │ │ │ ├── Starjhol.ttf │ │ │ │ ├── SWCrawlBody.ttf │ │ │ │ ├── StarJediBig.ttf │ │ │ │ ├── SWCrawlTitle.ttf │ │ │ │ ├── Star_Jedi_Rounded.ttf │ │ │ │ └── Franklin_Gothic_Book.ttf │ │ ├── Crawl View │ │ │ ├── BorderLabel │ │ │ │ ├── SWStrokedLogoLabel.h │ │ │ │ └── SWStrokedLogoLabel.m │ │ │ ├── SWCrawlView.h │ │ │ ├── SWCrawlView.xib │ │ │ └── SWCrawlView.m │ │ ├── Crawl │ │ │ ├── SWCrawl.h │ │ │ └── SWCrawl.m │ │ └── Constants │ │ │ ├── SWConstants.h │ │ │ └── SWConstants.m │ ├── ViewController.h │ ├── AppDelegate.h │ ├── main.m │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── ViewController.m │ ├── Info.plist │ ├── AppDelegate.m │ └── Base.lproj │ │ ├── Main.storyboard │ │ └── LaunchScreen.xib ├── SWCrawlViewExample.xcodeproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── project.pbxproj └── SWCrawlViewExampleTests │ ├── Info.plist │ └── SWCrawlViewExampleTests.m ├── .gitignore ├── LICENSE └── README.md /SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Assets/Images/mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MattFoley/SWCrawlView/HEAD/SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Assets/Images/mask.png -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Assets/Fonts/Starjedi.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MattFoley/SWCrawlView/HEAD/SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Assets/Fonts/Starjedi.ttf -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Assets/Fonts/Starjhol.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MattFoley/SWCrawlView/HEAD/SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Assets/Fonts/Starjhol.ttf -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Assets/Images/starBg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MattFoley/SWCrawlView/HEAD/SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Assets/Images/starBg.png -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Assets/Fonts/SWCrawlBody.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MattFoley/SWCrawlView/HEAD/SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Assets/Fonts/SWCrawlBody.ttf -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Assets/Fonts/StarJediBig.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MattFoley/SWCrawlView/HEAD/SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Assets/Fonts/StarJediBig.ttf -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Assets/Fonts/SWCrawlTitle.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MattFoley/SWCrawlView/HEAD/SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Assets/Fonts/SWCrawlTitle.ttf -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Assets/Fonts/Star_Jedi_Rounded.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MattFoley/SWCrawlView/HEAD/SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Assets/Fonts/Star_Jedi_Rounded.ttf -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Assets/Fonts/Franklin_Gothic_Book.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MattFoley/SWCrawlView/HEAD/SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Assets/Fonts/Franklin_Gothic_Book.ttf -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // SWCrawlViewExample 4 | // 5 | // Created by TJ Fallon on 5/21/15. 6 | // Copyright (c) 2015 TJ Fallon. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // SWCrawlViewExample 4 | // 5 | // Created by TJ Fallon on 5/21/15. 6 | // Copyright (c) 2015 TJ Fallon. 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 | -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // SWCrawlViewExample 4 | // 5 | // Created by TJ Fallon on 5/21/15. 6 | // Copyright (c) 2015 TJ Fallon. 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 | -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Crawl View/BorderLabel/SWStrokedLogoLabel.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWStrokedLogoLabel.h 3 | // 4 | // Created by Tj on 5/16/15. 5 | // Copyright (c) 2015 Tj. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | @interface SWStrokedLogoLabel : UILabel 11 | 12 | /** 13 | * This class is used for the main logo. 14 | */ 15 | @property IBInspectable UIColor *strokeColor; 16 | @property IBInspectable NSInteger strokeWidth; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # CocoaPods 21 | # 22 | # We recommend against adding the Pods directory to your .gitignore. However 23 | # you should judge for yourself, the pros and cons are mentioned at: 24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 25 | # 26 | #Pods/ 27 | -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExampleTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | foleyproductions.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * ---------------------------------------------------------------------------- 4 | * "THE BEER-WARE LICENSE" (Revision 501): 5 | * wrote this repo. As long as you retain this notice you 6 | * can do whatever you want with this stuff. If we meet some day, and you think 7 | * this stuff is worth it, you can buy me a beer in return. Tj Fallon 8 | * ---------------------------------------------------------------------------- 9 | */ 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 12 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 13 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 14 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 15 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 16 | OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 17 | THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Crawl/SWCrawl.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWCrawl.h 3 | // CrawlCreator2.0 4 | // 5 | // Created by Tj on 5/17/15. 6 | // Copyright (c) 2015 Tj. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | /** 13 | * This class exists to pass around data describing a Crawl object. 14 | */ 15 | @interface SWCrawl : NSObject 16 | 17 | @property NSString *introText; 18 | @property NSString *logoText; 19 | @property NSString *episodeNumberText; 20 | @property NSString *episodeTitleText; 21 | @property NSString *bodyText; 22 | 23 | @property UIFont *logoFont; 24 | @property UIFont *episodeTitleFont; 25 | @property UIFont *episodeNumberFont; 26 | @property UIFont *bodyFont; 27 | 28 | @property UIColor *logoStrokeColor; 29 | @property UIColor *episodeTitleColor; 30 | @property UIColor *episodeNumberColor; 31 | @property UIColor *bodyColor; 32 | 33 | - (NSAttributedString *)composedCrawlString; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Crawl View/BorderLabel/SWStrokedLogoLabel.m: -------------------------------------------------------------------------------- 1 | // 2 | // SWStrokedLogoLabel.m 3 | // 4 | // Created by Tj on 5/16/15. 5 | // Copyright (c) 2015 Tj. All rights reserved. 6 | // 7 | 8 | #import "SWStrokedLogoLabel.h" 9 | 10 | @implementation SWStrokedLogoLabel 11 | 12 | - (void)drawTextInRect:(CGRect)rect { 13 | 14 | CGSize shadowOffset = self.shadowOffset; 15 | UIColor *textColor = self.textColor; 16 | 17 | CGContextRef c = UIGraphicsGetCurrentContext(); 18 | CGContextSetLineWidth(c, self.strokeWidth); 19 | CGContextSetLineJoin(c, kCGLineJoinMiter); 20 | 21 | CGContextSetTextDrawingMode(c, kCGTextStroke); 22 | self.textColor = self.strokeColor; 23 | [super drawTextInRect:rect]; 24 | 25 | CGContextSetTextDrawingMode(c, kCGTextFill); 26 | self.textColor = textColor; 27 | self.shadowOffset = CGSizeMake(0, 0); 28 | [super drawTextInRect:rect]; 29 | 30 | self.shadowOffset = shadowOffset; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExampleTests/SWCrawlViewExampleTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // SWCrawlViewExampleTests.m 3 | // SWCrawlViewExampleTests 4 | // 5 | // Created by TJ Fallon on 5/21/15. 6 | // Copyright (c) 2015 TJ Fallon. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface SWCrawlViewExampleTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation SWCrawlViewExampleTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Constants/SWConstants.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWConstants.h 3 | // CrawlCreator2.0 4 | // 5 | // Created by Tj on 5/16/15. 6 | // Copyright (c) 2015 Tj. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | /** 13 | * These constants are designed to look as close to the theatrical Crawls as possible, using free to use fonts. 14 | * Improvements could be made by purchasing a mobile license to the Franklin Gothic Demi family, as is specified here: 15 | * http://www.theforce.net/fanfilms/postproduction/crawl/opening.asp 16 | * 17 | * Also, the StarJedi font that's being used seems to have some glyph sizing issues. 18 | * I've attempted to modify the font file to clean it up, but you may notice it act strangely. 19 | */ 20 | 21 | @interface SWConstants : NSObject 22 | 23 | UIColor* UIColorFromRGB(unsigned int rgbValue) ; 24 | 25 | + (UIColor *)starWarsLogoColor; 26 | + (UIFont *)starWarsLogoFont:(NSInteger)size; 27 | 28 | + (UIColor *)introTextColor; 29 | + (UIFont *)introTextFont:(NSInteger)size; 30 | 31 | + (UIColor *)crawlTextColor; 32 | 33 | + (UIFont *)bodyTextFont:(NSInteger)size; 34 | + (UIFont *)episodeTitleFont:(NSInteger)size; 35 | + (UIFont *)episodeNumberFont:(NSInteger)size; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "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 | } -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Constants/SWConstants.m: -------------------------------------------------------------------------------- 1 | // 2 | // SWConstants.m 3 | // CrawlCreator2.0 4 | // 5 | // Created by Tj on 5/16/15. 6 | // Copyright (c) 2015 Tj. All rights reserved. 7 | // 8 | 9 | #import "SWConstants.h" 10 | 11 | @implementation SWConstants 12 | 13 | UIColor* UIColorFromRGB(unsigned int rgbValue) { 14 | return [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 15 | green:((float)((rgbValue & 0xFF00) >> 8))/255.0 16 | blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]; 17 | } 18 | 19 | 20 | + (UIColor *)starWarsLogoColor 21 | { 22 | return UIColorFromRGB(0xe5b13a); 23 | } 24 | 25 | + (UIFont *)starWarsLogoFont:(NSInteger)size 26 | { 27 | return [UIFont fontWithName:@"StarJedi" size:size]; 28 | } 29 | 30 | + (UIColor *)introTextColor 31 | { 32 | return UIColorFromRGB(0x4bd5ee); 33 | } 34 | 35 | + (UIFont *)introTextFont:(NSInteger)size 36 | { 37 | return [UIFont fontWithName:@"Franklin Gothic Book" size:size]; 38 | } 39 | 40 | + (UIColor *)crawlTextColor 41 | { 42 | return UIColorFromRGB(0xe5b13a); 43 | } 44 | 45 | + (UIFont *)bodyTextFont:(NSInteger)size 46 | { 47 | return [UIFont fontWithName:@"SW Crawl Body" size:size]; 48 | } 49 | 50 | + (UIFont *)episodeTitleFont:(NSInteger)size 51 | { 52 | return [UIFont fontWithName:@"SW Crawl Title" size:size]; 53 | } 54 | 55 | + (UIFont *)episodeNumberFont:(NSInteger)size 56 | { 57 | return [UIFont fontWithName:@"SW Crawl Body" size:size]; 58 | } 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // SWCrawlViewExample 4 | // 5 | // Created by TJ Fallon on 5/21/15. 6 | // Copyright (c) 2015 TJ Fallon. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "SWCrawlView.h" 11 | #import "SWCrawl.h" 12 | 13 | @interface ViewController () 14 | 15 | @property (weak) IBOutlet SWCrawlView *crawlView; 16 | 17 | @end 18 | 19 | @implementation ViewController 20 | 21 | - (void)viewDidLoad { 22 | [super viewDidLoad]; 23 | 24 | SWCrawl *crawl = [SWCrawl new]; 25 | 26 | //Funny casing to use the characters in SW Jedi font that we need. 27 | [crawl setLogoText:@"Crawl\nWars"]; 28 | 29 | [crawl setEpisodeNumberText:@"Episode 6+"]; 30 | 31 | //Lowercase string because SW Title font has a couple funny characters in it. Check out the font. 32 | [crawl setEpisodeTitleText:@"Lorem Ipsum Strikes Back".lowercaseString]; 33 | [crawl setBodyText:@"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."]; 34 | 35 | [self.crawlView updateTextViaCrawl:crawl]; 36 | } 37 | 38 | - (UIStatusBarStyle)preferredStatusBarStyle 39 | { 40 | return UIStatusBarStyleLightContent; 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SWCrawlView 2 | 3 | This control provides a realistic and interactive version of the original Theatrical Crawl for use in any app. The control is fully customizable, fonts, colors, text, etc can all be modified. It supports all iOS Devices (not the watch yet, sorry.), and both orientations. Very specific implementations may require source code tweaking. 4 | 5 | 6 | 7 | #### Background 8 | A long time ago, in a city far, far away (Chicago, I miss you), I built an app that let you create and export HD crawl videos and could mux it with your own music files. The app has fallen into heavy neglect, and hasn't been updated since 2013. It barely works right now, but if you're curious, you can check it out [here.](https://itunes.apple.com/us/app/star-wars-crawl-creator/id494406923?mt=8) 9 | 10 | As you can tell from the more recent reviews, having been built for iOS 4, Crawl Creator needs a serious over haul. So, I'm rebuilding her from the ground up, and as part of that, I'm open sourcing the SWCrawlView that I've rebuilt. I may follow up by open sourcing the .MP4 creation and YouTube uploading when that's ready. 11 | 12 | ### How To Use It: 13 | 14 | It can be created either via a xib or initWithFrame. You can then edit it either one property at a time, or by creating a SWCrawl object and passing that in. Comments exist in the various headers to explain functionality, but the main class of interest will be "SWCrawlView" and "SWCrawl", the few others are just supporting files. 15 | 16 | If you want to use the default fonts that match the movie, you'll need to add the "Fonts provided by application" key to your info.plist file. The view will begin customized to match the movies, but all properties can be changed and a redraw will be forced when any property is changed. 17 | 18 | See the Info.plist of the SWCrawlViewExample project to see the "Fonts provided by application". 19 | 20 | A more detailed example project and documentation will follow soon. 21 | -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | foleyproductions.$(PRODUCT_NAME:rfc1034identifier) 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 | UIAppFonts 26 | 27 | Franklin_Gothic_Book.ttf 28 | StarJediBig.ttf 29 | SWCrawlBody.ttf 30 | Starjhol.ttf 31 | Star_Jedi_Rounded.ttf 32 | SWCrawlTitle.ttf 33 | 34 | UILaunchStoryboardName 35 | LaunchScreen 36 | UIMainStoryboardFile 37 | Main 38 | UIRequiredDeviceCapabilities 39 | 40 | armv7 41 | 42 | UISupportedInterfaceOrientations 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | UISupportedInterfaceOrientations~ipad 49 | 50 | UIInterfaceOrientationPortrait 51 | UIInterfaceOrientationPortraitUpsideDown 52 | UIInterfaceOrientationLandscapeLeft 53 | UIInterfaceOrientationLandscapeRight 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // SWCrawlViewExample 4 | // 5 | // Created by TJ Fallon on 5/21/15. 6 | // Copyright (c) 2015 TJ Fallon. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // 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. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // 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. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // 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. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Crawl View/SWCrawlView.h: -------------------------------------------------------------------------------- 1 | // 2 | // MFLCrawlView.h 3 | // CrawlCreator2.0 4 | // 5 | // Created by Tj on 5/16/15. 6 | // Copyright (c) 2015 Tj. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SWCrawl.h" 11 | 12 | //I know, it should really have a three letter class prefix, but I couldn't resist. 13 | @interface SWCrawlView : UIView 14 | 15 | #pragma mark Text Customization 16 | /** 17 | * e.g.: 18 | * STAR 19 | * WARS 20 | * 21 | * @param logoText Use new lines, it will not line break automatically. Will respect logoStrokeColor/Font, will always fill black. 22 | */ 23 | - (void)setLogoText:(NSString *)logoText; 24 | 25 | /** 26 | * e.g.: 27 | * Episode V 28 | * 29 | * @param numberText Number text to be set, can be nil. Will respect episodeNumberFont/Color 30 | */ 31 | - (void)setEpisodeNumberText:(NSString *)numberText; 32 | 33 | /** 34 | * e.g.: 35 | * THE EMPIRE STRIKES BACK 36 | * 37 | * @param titleText Title text to be set, can be nil. Will respect episodeTitleFont/Color 38 | */ 39 | - (void)setEpisodeTitleText:(NSString *)titleText; 40 | 41 | /** 42 | * e.g.: 43 | * 44 | * It is a dark time for the 45 | * Rebellion. Although the Death 46 | * Star has been destroyed. 47 | * 48 | * @param bodyText Text will be justified and broken into lines for you. Will respect bodyTextFont/Color 49 | */ 50 | - (void)setBodyText:(NSString *)bodyText; 51 | 52 | #pragma Update via SWCrawl 53 | /** 54 | * You can set all cusotmization values by creating an SWCrawl object and passing it in here. 55 | * Text values which are nil will be used, but font and color values which are nil will be ignored in favor of currently set values. 56 | * 57 | * @param crawl Customized SWCrawl object. 58 | */ 59 | - (void)updateTextViaCrawl:(SWCrawl *)crawl; 60 | 61 | 62 | /** 63 | * This method will return a SWCrawl object with all the current properties of the view set. 64 | * 65 | * @return Customized SWCrawl object 66 | */ 67 | - (SWCrawl *)crawlForCurrentText; 68 | 69 | 70 | /** 71 | * This will return an NSAttributedString of the episode number, episode title, and crawl body merged together. 72 | * This string is used internally to display the crawl. 73 | * 74 | * @return Crawl string, including all text style customizations. 75 | */ 76 | - (NSAttributedString *)composedCrawlString; 77 | 78 | #pragma mark Font/Color Customization 79 | 80 | /** 81 | * See above text comments for descriptions of each value in the crawl. Setting any of these will update the force a redraw on the crawl view. 82 | */ 83 | @property (nonatomic) UIFont *logoFont; 84 | @property (nonatomic) UIFont *episodeTitleFont; 85 | @property (nonatomic) UIFont *episodeNumberFont; 86 | @property (nonatomic) UIFont *bodyFont; 87 | 88 | @property (nonatomic) UIColor *logoStrokeColor; 89 | @property (nonatomic) UIColor *episodeTitleColor; 90 | @property (nonatomic) UIColor *episodeNumberColor; 91 | @property (nonatomic) UIColor *bodyColor; 92 | 93 | @property (readonly) BOOL isAnimating; 94 | 95 | - (void)redisplayAfterScrollOut; 96 | - (void)scrollOutWithDuration:(CGFloat)duration 97 | completion:(void(^)(void))completion; 98 | 99 | @end 100 | -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Crawl/SWCrawl.m: -------------------------------------------------------------------------------- 1 | // 2 | // SWCrawl.m 3 | // CrawlCreator2.0 4 | // 5 | // Created by Tj on 5/17/15. 6 | // Copyright (c) 2015 Tj. All rights reserved. 7 | // 8 | 9 | #import "SWCrawl.h" 10 | #import 11 | 12 | @implementation SWCrawl 13 | 14 | - (id)copyWithZone:(NSZone *)zone 15 | { 16 | SWCrawl *newCrawl = [[[self class] allocWithZone:zone] init]; 17 | 18 | if (newCrawl) { 19 | newCrawl.introText = self.introText; 20 | newCrawl.logoText = self.logoText; 21 | newCrawl.episodeNumberText = self.episodeNumberText; 22 | newCrawl.episodeTitleText = self.episodeTitleText; 23 | newCrawl.bodyText = self.bodyText; 24 | 25 | newCrawl.logoFont = self.logoFont; 26 | newCrawl.episodeTitleFont = self.episodeTitleFont; 27 | newCrawl.episodeNumberFont = self.episodeNumberFont; 28 | newCrawl.bodyFont = self.bodyFont; 29 | 30 | newCrawl.logoStrokeColor = self.logoStrokeColor; 31 | newCrawl.episodeTitleColor = self.episodeTitleColor; 32 | newCrawl.episodeNumberColor = self.episodeNumberColor; 33 | newCrawl.bodyColor = self.bodyColor; 34 | } 35 | 36 | return newCrawl; 37 | } 38 | 39 | 40 | - (NSAttributedString *)composedCrawlString 41 | { 42 | NSMutableAttributedString *fullCrawlString = [NSMutableAttributedString new]; 43 | 44 | if (self.episodeNumberText.length) { 45 | NSMutableParagraphStyle *numberTextParagraphStyle = [NSMutableParagraphStyle new]; 46 | numberTextParagraphStyle.alignment = NSTextAlignmentCenter; 47 | 48 | NSDictionary *numberAttributes = @{ NSParagraphStyleAttributeName : numberTextParagraphStyle, 49 | NSForegroundColorAttributeName : self.episodeNumberColor, 50 | NSFontAttributeName : self.episodeNumberFont}; 51 | 52 | NSString *spacedNumberString = [NSString stringWithFormat:@"%@\n\n", self.episodeNumberText]; 53 | NSAttributedString *numberString = [[NSAttributedString alloc] initWithString:spacedNumberString 54 | attributes:numberAttributes]; 55 | 56 | [fullCrawlString appendAttributedString:numberString]; 57 | } 58 | 59 | if (self.episodeTitleText.length) { 60 | NSMutableParagraphStyle *titleTextParagraphStyle = [NSMutableParagraphStyle new]; 61 | titleTextParagraphStyle.alignment = NSTextAlignmentCenter; 62 | 63 | NSDictionary *titleAttributes = @{ NSParagraphStyleAttributeName : titleTextParagraphStyle, 64 | NSForegroundColorAttributeName : self.episodeTitleColor, 65 | NSFontAttributeName : self.episodeTitleFont}; 66 | NSString *spacedTitleString = [NSString stringWithFormat:@"%@\n\n", self.episodeTitleText]; 67 | NSAttributedString *titleString = [[NSAttributedString alloc] initWithString:spacedTitleString 68 | attributes:titleAttributes]; 69 | 70 | [fullCrawlString appendAttributedString:titleString]; 71 | } 72 | 73 | if (self.bodyText.length) { 74 | NSMutableParagraphStyle *bodyTextParagraphStyle = [NSMutableParagraphStyle new]; 75 | bodyTextParagraphStyle.alignment = NSTextAlignmentJustified; 76 | bodyTextParagraphStyle.firstLineHeadIndent = 0.05; // "Very IMP" said original comment, why? Tj- 77 | 78 | NSDictionary *bodyAttributes = @{ NSParagraphStyleAttributeName : bodyTextParagraphStyle, 79 | NSForegroundColorAttributeName : self.bodyColor, 80 | NSFontAttributeName : self.bodyFont }; 81 | 82 | NSAttributedString *bodyString = [[NSAttributedString alloc] initWithString:self.bodyText 83 | attributes:bodyAttributes]; 84 | [fullCrawlString appendAttributedString:bodyString]; 85 | } 86 | 87 | return fullCrawlString; 88 | } 89 | 90 | @end 91 | -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Crawl View/SWCrawlView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | StarJedi 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample/SWCrawlView/Crawl View/SWCrawlView.m: -------------------------------------------------------------------------------- 1 | // 2 | // MFLCrawlView.m 3 | // CrawlCreator2.0 4 | // 5 | // Created by Tj on 5/16/15. 6 | // Copyright (c) 2015 Tj. All rights reserved. 7 | // 8 | 9 | #import "SWCrawlView.h" 10 | #import "SWConstants.h" 11 | #import "SWStrokedLogoLabel.h" 12 | #import 13 | 14 | #ifndef UIInterfaceIdiomIsPad 15 | #define UIInterfaceIdiomIsPad() (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) 16 | #endif 17 | 18 | const CGFloat logoStrokeSizeForFontPointSizeMultiplier = .165; 19 | 20 | @interface SWCrawlView () 21 | 22 | @property (weak) IBOutlet UIView *xibView; 23 | @property (weak) IBOutlet UIView *screenSizeScaleView; 24 | 25 | @property (weak) IBOutlet UIImageView *maskImageView; 26 | @property (weak) IBOutlet UIScrollView *scrollView; 27 | @property (weak) IBOutlet UIScrollView *controlView; 28 | 29 | @property (weak) IBOutlet UILabel *crawlTextView; 30 | @property (weak) IBOutlet NSLayoutConstraint *crawlTextTopSpacingConstraint; 31 | @property (weak) IBOutlet NSLayoutConstraint *crawlTextBottomSpacingConstraint; 32 | 33 | @property (weak) IBOutlet SWStrokedLogoLabel *logoLabel; 34 | @property (weak) IBOutlet NSLayoutConstraint *logoWidthConstraint; 35 | @property (weak) IBOutlet NSLayoutConstraint *logoHeightConstraint; 36 | @property (weak) IBOutlet UILabel *titleLabel; 37 | 38 | @property (readwrite) BOOL isAnimating; 39 | 40 | @property SWCrawl *crawl; 41 | 42 | @end 43 | 44 | @implementation SWCrawlView 45 | 46 | #pragma mark Init 47 | - (id)initWithFrame:(CGRect)frame 48 | { 49 | self = [super initWithFrame:frame]; 50 | 51 | if (self) { 52 | [self sharedInit]; 53 | } 54 | 55 | return self; 56 | } 57 | 58 | - (id)initWithCoder:(NSCoder *)aDecoder 59 | { 60 | self = [super initWithCoder:aDecoder]; 61 | 62 | if (self) { 63 | [self sharedInit]; 64 | } 65 | 66 | return self; 67 | } 68 | 69 | - (void)sharedInit 70 | { 71 | _crawl = [SWCrawl new]; 72 | 73 | _crawl.logoStrokeColor = [SWConstants starWarsLogoColor]; 74 | _crawl.episodeNumberColor = [SWConstants crawlTextColor]; 75 | _crawl.episodeTitleColor = [SWConstants crawlTextColor]; 76 | _crawl.bodyColor = [SWConstants crawlTextColor]; 77 | 78 | _crawl.logoFont = [SWConstants starWarsLogoFont:UIInterfaceIdiomIsPad() ? 140 : 48]; 79 | _crawl.episodeNumberFont = [SWConstants episodeNumberFont:20]; 80 | _crawl.episodeTitleFont = [SWConstants episodeTitleFont:40]; 81 | _crawl.bodyFont = [SWConstants bodyTextFont:20]; 82 | 83 | [self unwrapNib]; 84 | 85 | [self startObservingScrollChanges]; 86 | [self beginOrientationObserving]; 87 | 88 | [self orientationDidChange:nil]; 89 | } 90 | 91 | - (void)unwrapNib 92 | { 93 | [[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self.class) 94 | owner:self 95 | options:nil]; 96 | 97 | [self.xibView setTranslatesAutoresizingMaskIntoConstraints:NO]; 98 | [self.xibView setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"starBg.png"]]]; 99 | [self addSubview:self.xibView]; 100 | 101 | NSDictionary *views = NSDictionaryOfVariableBindings(_xibView); 102 | [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_xibView]|" 103 | options:0 104 | metrics:nil 105 | views:views]]; 106 | [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_xibView]|" 107 | options:0 108 | metrics:nil 109 | views:views]]; 110 | } 111 | 112 | #pragma mark Customization 113 | 114 | - (void)updateTextViaCrawl:(SWCrawl *)crawl 115 | { 116 | [self setLogoText:crawl.logoText]; 117 | [self setLogoFont:crawl.logoFont]; 118 | [self setLogoStrokeColor:crawl.logoStrokeColor]; 119 | 120 | [self setEpisodeNumberText:crawl.episodeNumberText]; 121 | [self setEpisodeNumberFont:crawl.episodeNumberFont]; 122 | [self setEpisodeNumberColor:crawl.episodeNumberColor]; 123 | 124 | [self setEpisodeTitleText:crawl.episodeTitleText]; 125 | [self setEpisodeTitleColor:crawl.episodeTitleColor]; 126 | [self setEpisodeTitleFont:crawl.episodeTitleFont]; 127 | 128 | [self setBodyText:crawl.bodyText]; 129 | [self setBodyColor:crawl.bodyColor]; 130 | [self setBodyFont:crawl.bodyFont]; 131 | } 132 | 133 | - (SWCrawl *)crawlForCurrentText 134 | { 135 | return self.crawl; 136 | } 137 | 138 | - (NSAttributedString *)composedCrawlString 139 | { 140 | return [self.crawl composedCrawlString]; 141 | } 142 | 143 | - (void)updateCrawlingText 144 | { 145 | [self.crawlTextView setAttributedText:[self composedCrawlString]]; 146 | 147 | [self setNeedsUpdateConstraints]; 148 | [self layoutIfNeeded]; 149 | 150 | [self scrollViewDidScroll:self.scrollView]; 151 | } 152 | 153 | #pragma mark Setters 154 | 155 | - (void)setEpisodeNumberText:(NSString *)numberText 156 | { 157 | self.crawl.episodeNumberText = numberText; 158 | [self updateCrawlingText]; 159 | } 160 | 161 | - (void)setEpisodeTitleText:(NSString *)titleText 162 | { 163 | self.crawl.episodeTitleText = titleText; 164 | [self updateCrawlingText]; 165 | } 166 | 167 | - (void)setBodyText:(NSString *)bodyText 168 | { 169 | self.crawl.bodyText = bodyText; 170 | [self updateCrawlingText]; 171 | } 172 | 173 | - (void)setLogoText:(NSString *)logoText 174 | { 175 | [self.logoLabel setStrokeColor:self.crawl.logoStrokeColor]; 176 | [self.logoLabel setFont:self.crawl.logoFont]; 177 | [self.logoLabel setText:logoText]; 178 | [self.logoLabel setStrokeWidth:self.crawl.logoFont.pointSize * logoStrokeSizeForFontPointSizeMultiplier]; 179 | [self.crawl setLogoText:logoText]; 180 | } 181 | 182 | - (void)setLogoFont:(UIFont *)logoFont 183 | { 184 | if (logoFont) { 185 | _logoFont = logoFont; 186 | 187 | self.crawl.logoFont = logoFont; 188 | [self updateCrawlingText]; 189 | } 190 | } 191 | 192 | - (void)setBodyFont:(UIFont *)bodyFont 193 | { 194 | if (bodyFont) { 195 | _bodyFont = bodyFont; 196 | 197 | self.crawl.bodyFont = bodyFont; 198 | [self updateCrawlingText]; 199 | } 200 | } 201 | 202 | - (void)setEpisodeTitleFont:(UIFont *)episodeTitleFont 203 | { 204 | if (episodeTitleFont) { 205 | _episodeTitleFont = episodeTitleFont; 206 | 207 | self.crawl.episodeTitleFont = episodeTitleFont; 208 | [self updateCrawlingText]; 209 | } 210 | } 211 | 212 | - (void)setEpisodeNumberFont:(UIFont *)episodeNumberFont 213 | { 214 | if (episodeNumberFont) { 215 | _episodeNumberFont = episodeNumberFont; 216 | 217 | self.crawl.episodeNumberFont = episodeNumberFont; 218 | [self updateCrawlingText]; 219 | } 220 | } 221 | 222 | - (void)setLogoStrokeColor:(UIColor *)logoStrokeColor 223 | { 224 | if (logoStrokeColor) { 225 | _logoStrokeColor = logoStrokeColor; 226 | 227 | self.crawl.logoStrokeColor = logoStrokeColor; 228 | [self updateCrawlingText]; 229 | } 230 | } 231 | 232 | - (void)setBodyColor:(UIColor *)bodyColor 233 | { 234 | if (bodyColor) { 235 | _bodyColor = bodyColor; 236 | 237 | self.crawl.bodyColor = bodyColor; 238 | [self updateCrawlingText]; 239 | } 240 | } 241 | 242 | - (void)setEpisodeTitleColor:(UIColor *)episodeTitleColor 243 | { 244 | if (episodeTitleColor) { 245 | _episodeTitleColor = episodeTitleColor; 246 | 247 | self.crawl.episodeTitleColor = episodeTitleColor; 248 | [self updateCrawlingText]; 249 | } 250 | } 251 | 252 | - (void)setEpisodeNumberColor:(UIColor *)episodeNumberColor 253 | { 254 | if (episodeNumberColor) { 255 | _episodeNumberColor = episodeNumberColor; 256 | 257 | self.crawl.episodeNumberColor = episodeNumberColor; 258 | [self updateCrawlingText]; 259 | } 260 | } 261 | 262 | #pragma mark Scroll Handling 263 | 264 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView 265 | { 266 | if (!self.isAnimating) { 267 | CGFloat distanceFromVisible = (scrollView.contentOffset.y * 2) + CGRectGetHeight(self.frame); 268 | CGFloat logoScaleTransformValue = (1.0 - (distanceFromVisible / self.crawlTextTopSpacingConstraint.constant)) * 269 | [self logoScaleForScreenSize]; 270 | 271 | [self.logoLabel setHidden:(logoScaleTransformValue <= 0)]; 272 | 273 | if (logoScaleTransformValue > 0) { 274 | CGAffineTransform scaleTransform = CGAffineTransformMakeScale(logoScaleTransformValue, 275 | logoScaleTransformValue); 276 | 277 | [self.logoLabel setTransform:scaleTransform]; 278 | } 279 | } 280 | } 281 | 282 | static int kObservingContentSizeChangesContext; 283 | static int kObservingContentOffsetChangesContext; 284 | 285 | - (void)startObservingScrollChanges 286 | { 287 | [self.scrollView addObserver:self 288 | forKeyPath:@"contentSize" 289 | options:0 290 | context:&kObservingContentSizeChangesContext]; 291 | [self.controlView addObserver:self 292 | forKeyPath:@"contentOffset" 293 | options:0 294 | context:&kObservingContentOffsetChangesContext]; 295 | } 296 | 297 | - (void)stopObservingScrollChanges 298 | { 299 | [self.controlView removeObserver:self 300 | forKeyPath:@"contentOffset" 301 | context:&kObservingContentOffsetChangesContext]; 302 | 303 | [self.scrollView removeObserver:self 304 | forKeyPath:@"contentSize" 305 | context:&kObservingContentSizeChangesContext]; 306 | } 307 | 308 | - (void)observeValueForKeyPath:(NSString *)keyPath 309 | ofObject:(id)object 310 | change:(NSDictionary *)change 311 | context:(void *)context 312 | { 313 | UIScrollView *scrollView = object; 314 | if (context == &kObservingContentSizeChangesContext) { 315 | [self.controlView setContentSize:scrollView.contentSize]; 316 | } else if (context == &kObservingContentOffsetChangesContext) { 317 | [self.scrollView setContentOffset:scrollView.contentOffset animated:NO]; 318 | } else { 319 | [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; 320 | } 321 | } 322 | 323 | #pragma mark Orientation Handling 324 | 325 | - (void)beginOrientationObserving 326 | { 327 | [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; 328 | [[NSNotificationCenter defaultCenter] addObserver:self 329 | selector:@selector(orientationDidChange:) 330 | name:UIDeviceOrientationDidChangeNotification object:nil]; 331 | } 332 | 333 | - (void)orientationDidChange:(id)sender 334 | { 335 | UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; 336 | 337 | if (UIInterfaceOrientationIsLandscape(orientation)) { 338 | [self setupTransformsForLandscape]; 339 | } else { 340 | [self setupTranformsForPortrait]; 341 | } 342 | } 343 | 344 | 345 | //These transforms, which modify the m34, are how we acheive the perspective effect. 346 | //I was never very good at matrix math, so that's the best explanation I have. 347 | 348 | //This transform is not as movie accurate, but is more readable for portrait. 349 | - (void)setupTranformsForPortrait 350 | { 351 | CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity; 352 | rotationAndPerspectiveTransform.m34 = 1.0 / -550; 353 | rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, 354 | 80.0f * M_PI / 165.0f, 1.0f, 0.0f, 0.0f); 355 | rotationAndPerspectiveTransform = CATransform3DScale(rotationAndPerspectiveTransform, [self crawlScaleforScreenSize], 356 | [self crawlScaleforScreenSize], 1); 357 | rotationAndPerspectiveTransform = CATransform3DTranslate(rotationAndPerspectiveTransform, 0, 0, -250); 358 | 359 | CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath: @"transform"]; 360 | transformAnimation.fromValue = [NSValue valueWithCATransform3D:[((CALayer *)self.scrollView.layer.presentationLayer) transform]]; 361 | transformAnimation.toValue = [NSValue valueWithCATransform3D:rotationAndPerspectiveTransform]; 362 | transformAnimation.duration = 3; 363 | [self.scrollView.layer addAnimation:transformAnimation forKey:@"transform"]; 364 | [self.scrollView.layer setTransform:rotationAndPerspectiveTransform]; 365 | 366 | [self.logoLabel.layer setZPosition:1000]; 367 | [self.maskImageView.layer setZPosition:1000]; 368 | } 369 | 370 | //This transform more accurately reflects the movie's angle. 371 | - (void)setupTransformsForLandscape 372 | { 373 | CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity; 374 | rotationAndPerspectiveTransform.m34 = 1.0 / -700; 375 | rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, 376 | 80.0f * M_PI / 155.0f, 1.0f, 0.0f, 0.0f); 377 | rotationAndPerspectiveTransform = CATransform3DScale(rotationAndPerspectiveTransform, [self crawlScaleforScreenSize], 378 | [self crawlScaleforScreenSize], 1); 379 | rotationAndPerspectiveTransform = CATransform3DTranslate(rotationAndPerspectiveTransform, 0, 0, -250); 380 | 381 | CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath: @"transform"]; 382 | transformAnimation.fromValue = [NSValue valueWithCATransform3D:[((CALayer *)self.scrollView.layer.presentationLayer) transform]]; 383 | transformAnimation.toValue = [NSValue valueWithCATransform3D:rotationAndPerspectiveTransform]; 384 | transformAnimation.duration = 3; 385 | [self.scrollView.layer addAnimation:transformAnimation forKey:@"transform"]; 386 | [self.scrollView.layer setTransform:rotationAndPerspectiveTransform]; 387 | 388 | [self.logoLabel.layer setZPosition:1000]; 389 | [self.maskImageView.layer setZPosition:1000]; 390 | } 391 | 392 | #pragma mark Device Specific Tweaks 393 | 394 | - (CGFloat)crawlScaleforScreenSize 395 | { 396 | CGFloat scaleSize = 1; 397 | if (UIInterfaceIdiomIsPad()) { 398 | scaleSize = 1.4; 399 | } else { 400 | scaleSize = 1; 401 | } 402 | 403 | return scaleSize; 404 | } 405 | 406 | - (CGFloat)logoScaleForScreenSize 407 | { 408 | CGFloat scaleSize; 409 | UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; 410 | if (UIInterfaceOrientationIsLandscape(orientation)) { 411 | scaleSize = UIInterfaceIdiomIsPad() ? 2.0 : 2.0; 412 | } else { 413 | scaleSize = UIInterfaceIdiomIsPad() ? 3.0 : 2.5; 414 | } 415 | return scaleSize; 416 | } 417 | 418 | - (void)redisplayAfterScrollOut 419 | { 420 | [UIView animateWithDuration:1.0 animations:^{ 421 | [self.scrollView setAlpha:1]; 422 | [self.logoLabel setAlpha:1]; 423 | [self.controlView setContentOffset:CGPointMake(0, 0)]; 424 | }]; 425 | } 426 | 427 | - (void)scrollOutWithDuration:(CGFloat)duration 428 | completion:(void(^)(void))completion; 429 | { 430 | self.isAnimating = YES; 431 | CGFloat delay = 0.0; 432 | CGFloat visibleTextOffset = (self.crawlTextTopSpacingConstraint.constant - CGRectGetHeight(self.bounds)); 433 | if (self.scrollView.contentOffset.y < visibleTextOffset) { 434 | CGFloat distanceToGo = visibleTextOffset - self.scrollView.contentOffset.y; 435 | CGFloat percentageOfWholeDistance = distanceToGo / self.scrollView.contentSize.height; 436 | delay = duration * percentageOfWholeDistance; 437 | 438 | [UIView animateWithDuration:delay animations:^{ 439 | [self.logoLabel setTransform:CGAffineTransformMakeScale(.001, .001)]; 440 | }]; 441 | } 442 | 443 | [UIView animateWithDuration:duration 444 | delay:0.0 445 | options:UIViewAnimationOptionCurveEaseIn 446 | animations:^{ 447 | [self.controlView setContentOffset:CGPointMake(0, (self.controlView.contentSize.height))]; 448 | } completion:^(BOOL finished) { 449 | if (completion) { 450 | completion(); 451 | } 452 | self.isAnimating = NO; 453 | [self.scrollView setAlpha:0]; 454 | [self.logoLabel setAlpha:0]; 455 | }]; 456 | } 457 | 458 | @end 459 | -------------------------------------------------------------------------------- /SWCrawlViewExample/SWCrawlViewExample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | D933DF2A1B0E155100050E6B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D933DF291B0E155100050E6B /* main.m */; }; 11 | D933DF2D1B0E155100050E6B /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D933DF2C1B0E155100050E6B /* AppDelegate.m */; }; 12 | D933DF301B0E155100050E6B /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D933DF2F1B0E155100050E6B /* ViewController.m */; }; 13 | D933DF331B0E155100050E6B /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D933DF311B0E155100050E6B /* Main.storyboard */; }; 14 | D933DF351B0E155100050E6B /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D933DF341B0E155100050E6B /* Images.xcassets */; }; 15 | D933DF381B0E155100050E6B /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = D933DF361B0E155100050E6B /* LaunchScreen.xib */; }; 16 | D933DF441B0E155100050E6B /* SWCrawlViewExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D933DF431B0E155100050E6B /* SWCrawlViewExampleTests.m */; }; 17 | D933DF581B0E165D00050E6B /* SWConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = D933DF501B0E165D00050E6B /* SWConstants.m */; }; 18 | D933DF591B0E165D00050E6B /* SWCrawl.m in Sources */ = {isa = PBXBuildFile; fileRef = D933DF531B0E165D00050E6B /* SWCrawl.m */; }; 19 | D933DF5A1B0E165D00050E6B /* SWCrawlView.m in Sources */ = {isa = PBXBuildFile; fileRef = D933DF561B0E165D00050E6B /* SWCrawlView.m */; }; 20 | D933DF5B1B0E165D00050E6B /* SWCrawlView.xib in Resources */ = {isa = PBXBuildFile; fileRef = D933DF571B0E165D00050E6B /* SWCrawlView.xib */; }; 21 | D933DF6E1B0E18C700050E6B /* SWStrokedLogoLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = D933DF6D1B0E18C700050E6B /* SWStrokedLogoLabel.m */; }; 22 | D9A13BF81B0E5484000ED3E7 /* Franklin_Gothic_Book.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D9A13BEE1B0E5483000ED3E7 /* Franklin_Gothic_Book.ttf */; }; 23 | D9A13BF91B0E5484000ED3E7 /* Star_Jedi_Rounded.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D9A13BEF1B0E5483000ED3E7 /* Star_Jedi_Rounded.ttf */; }; 24 | D9A13BFA1B0E5484000ED3E7 /* Starjedi.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D9A13BF01B0E5483000ED3E7 /* Starjedi.ttf */; }; 25 | D9A13BFB1B0E5484000ED3E7 /* StarJediBig.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D9A13BF11B0E5483000ED3E7 /* StarJediBig.ttf */; }; 26 | D9A13BFC1B0E5484000ED3E7 /* Starjhol.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D9A13BF21B0E5483000ED3E7 /* Starjhol.ttf */; }; 27 | D9A13BFD1B0E5484000ED3E7 /* SWCrawlBody.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D9A13BF31B0E5483000ED3E7 /* SWCrawlBody.ttf */; }; 28 | D9A13BFE1B0E5484000ED3E7 /* SWCrawlTitle.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D9A13BF41B0E5484000ED3E7 /* SWCrawlTitle.ttf */; }; 29 | D9A13BFF1B0E5484000ED3E7 /* mask.png in Resources */ = {isa = PBXBuildFile; fileRef = D9A13BF61B0E5484000ED3E7 /* mask.png */; }; 30 | D9A13C001B0E5484000ED3E7 /* starBg.png in Resources */ = {isa = PBXBuildFile; fileRef = D9A13BF71B0E5484000ED3E7 /* starBg.png */; }; 31 | /* End PBXBuildFile section */ 32 | 33 | /* Begin PBXContainerItemProxy section */ 34 | D933DF3E1B0E155100050E6B /* PBXContainerItemProxy */ = { 35 | isa = PBXContainerItemProxy; 36 | containerPortal = D933DF1C1B0E155100050E6B /* Project object */; 37 | proxyType = 1; 38 | remoteGlobalIDString = D933DF231B0E155100050E6B; 39 | remoteInfo = SWCrawlViewExample; 40 | }; 41 | /* End PBXContainerItemProxy section */ 42 | 43 | /* Begin PBXFileReference section */ 44 | D933DF241B0E155100050E6B /* SWCrawlViewExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SWCrawlViewExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 45 | D933DF281B0E155100050E6B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 46 | D933DF291B0E155100050E6B /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 47 | D933DF2B1B0E155100050E6B /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 48 | D933DF2C1B0E155100050E6B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 49 | D933DF2E1B0E155100050E6B /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 50 | D933DF2F1B0E155100050E6B /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 51 | D933DF321B0E155100050E6B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 52 | D933DF341B0E155100050E6B /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 53 | D933DF371B0E155100050E6B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 54 | D933DF3D1B0E155100050E6B /* SWCrawlViewExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SWCrawlViewExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 55 | D933DF421B0E155100050E6B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 56 | D933DF431B0E155100050E6B /* SWCrawlViewExampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SWCrawlViewExampleTests.m; sourceTree = ""; }; 57 | D933DF4F1B0E165D00050E6B /* SWConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SWConstants.h; sourceTree = ""; }; 58 | D933DF501B0E165D00050E6B /* SWConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SWConstants.m; sourceTree = ""; }; 59 | D933DF521B0E165D00050E6B /* SWCrawl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SWCrawl.h; sourceTree = ""; }; 60 | D933DF531B0E165D00050E6B /* SWCrawl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SWCrawl.m; sourceTree = ""; }; 61 | D933DF551B0E165D00050E6B /* SWCrawlView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SWCrawlView.h; sourceTree = ""; }; 62 | D933DF561B0E165D00050E6B /* SWCrawlView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SWCrawlView.m; sourceTree = ""; }; 63 | D933DF571B0E165D00050E6B /* SWCrawlView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SWCrawlView.xib; sourceTree = ""; }; 64 | D933DF6C1B0E18C700050E6B /* SWStrokedLogoLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SWStrokedLogoLabel.h; sourceTree = ""; }; 65 | D933DF6D1B0E18C700050E6B /* SWStrokedLogoLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SWStrokedLogoLabel.m; sourceTree = ""; }; 66 | D9A13BEE1B0E5483000ED3E7 /* Franklin_Gothic_Book.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Franklin_Gothic_Book.ttf; sourceTree = ""; }; 67 | D9A13BEF1B0E5483000ED3E7 /* Star_Jedi_Rounded.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Star_Jedi_Rounded.ttf; sourceTree = ""; }; 68 | D9A13BF01B0E5483000ED3E7 /* Starjedi.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Starjedi.ttf; sourceTree = ""; }; 69 | D9A13BF11B0E5483000ED3E7 /* StarJediBig.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = StarJediBig.ttf; sourceTree = ""; }; 70 | D9A13BF21B0E5483000ED3E7 /* Starjhol.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Starjhol.ttf; sourceTree = ""; }; 71 | D9A13BF31B0E5483000ED3E7 /* SWCrawlBody.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = SWCrawlBody.ttf; sourceTree = ""; }; 72 | D9A13BF41B0E5484000ED3E7 /* SWCrawlTitle.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = SWCrawlTitle.ttf; sourceTree = ""; }; 73 | D9A13BF61B0E5484000ED3E7 /* mask.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = mask.png; sourceTree = ""; }; 74 | D9A13BF71B0E5484000ED3E7 /* starBg.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = starBg.png; sourceTree = ""; }; 75 | /* End PBXFileReference section */ 76 | 77 | /* Begin PBXFrameworksBuildPhase section */ 78 | D933DF211B0E155100050E6B /* Frameworks */ = { 79 | isa = PBXFrameworksBuildPhase; 80 | buildActionMask = 2147483647; 81 | files = ( 82 | ); 83 | runOnlyForDeploymentPostprocessing = 0; 84 | }; 85 | D933DF3A1B0E155100050E6B /* Frameworks */ = { 86 | isa = PBXFrameworksBuildPhase; 87 | buildActionMask = 2147483647; 88 | files = ( 89 | ); 90 | runOnlyForDeploymentPostprocessing = 0; 91 | }; 92 | /* End PBXFrameworksBuildPhase section */ 93 | 94 | /* Begin PBXGroup section */ 95 | D933DF1B1B0E155100050E6B = { 96 | isa = PBXGroup; 97 | children = ( 98 | D933DF261B0E155100050E6B /* SWCrawlViewExample */, 99 | D933DF401B0E155100050E6B /* SWCrawlViewExampleTests */, 100 | D933DF251B0E155100050E6B /* Products */, 101 | ); 102 | sourceTree = ""; 103 | }; 104 | D933DF251B0E155100050E6B /* Products */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | D933DF241B0E155100050E6B /* SWCrawlViewExample.app */, 108 | D933DF3D1B0E155100050E6B /* SWCrawlViewExampleTests.xctest */, 109 | ); 110 | name = Products; 111 | sourceTree = ""; 112 | }; 113 | D933DF261B0E155100050E6B /* SWCrawlViewExample */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | D933DF2B1B0E155100050E6B /* AppDelegate.h */, 117 | D933DF2C1B0E155100050E6B /* AppDelegate.m */, 118 | D933DF2E1B0E155100050E6B /* ViewController.h */, 119 | D933DF2F1B0E155100050E6B /* ViewController.m */, 120 | D933DF4D1B0E165D00050E6B /* SWCrawlView */, 121 | D933DF311B0E155100050E6B /* Main.storyboard */, 122 | D933DF341B0E155100050E6B /* Images.xcassets */, 123 | D933DF361B0E155100050E6B /* LaunchScreen.xib */, 124 | D933DF271B0E155100050E6B /* Supporting Files */, 125 | ); 126 | path = SWCrawlViewExample; 127 | sourceTree = ""; 128 | }; 129 | D933DF271B0E155100050E6B /* Supporting Files */ = { 130 | isa = PBXGroup; 131 | children = ( 132 | D933DF281B0E155100050E6B /* Info.plist */, 133 | D933DF291B0E155100050E6B /* main.m */, 134 | ); 135 | name = "Supporting Files"; 136 | sourceTree = ""; 137 | }; 138 | D933DF401B0E155100050E6B /* SWCrawlViewExampleTests */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | D933DF431B0E155100050E6B /* SWCrawlViewExampleTests.m */, 142 | D933DF411B0E155100050E6B /* Supporting Files */, 143 | ); 144 | path = SWCrawlViewExampleTests; 145 | sourceTree = ""; 146 | }; 147 | D933DF411B0E155100050E6B /* Supporting Files */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | D933DF421B0E155100050E6B /* Info.plist */, 151 | ); 152 | name = "Supporting Files"; 153 | sourceTree = ""; 154 | }; 155 | D933DF4D1B0E165D00050E6B /* SWCrawlView */ = { 156 | isa = PBXGroup; 157 | children = ( 158 | D9A13BEC1B0E5483000ED3E7 /* Assets */, 159 | D933DF4E1B0E165D00050E6B /* Constants */, 160 | D933DF511B0E165D00050E6B /* Crawl */, 161 | D933DF541B0E165D00050E6B /* Crawl View */, 162 | ); 163 | path = SWCrawlView; 164 | sourceTree = ""; 165 | }; 166 | D933DF4E1B0E165D00050E6B /* Constants */ = { 167 | isa = PBXGroup; 168 | children = ( 169 | D933DF4F1B0E165D00050E6B /* SWConstants.h */, 170 | D933DF501B0E165D00050E6B /* SWConstants.m */, 171 | ); 172 | path = Constants; 173 | sourceTree = ""; 174 | }; 175 | D933DF511B0E165D00050E6B /* Crawl */ = { 176 | isa = PBXGroup; 177 | children = ( 178 | D933DF521B0E165D00050E6B /* SWCrawl.h */, 179 | D933DF531B0E165D00050E6B /* SWCrawl.m */, 180 | ); 181 | path = Crawl; 182 | sourceTree = ""; 183 | }; 184 | D933DF541B0E165D00050E6B /* Crawl View */ = { 185 | isa = PBXGroup; 186 | children = ( 187 | D933DF6B1B0E18C700050E6B /* Logo Label */, 188 | D933DF551B0E165D00050E6B /* SWCrawlView.h */, 189 | D933DF561B0E165D00050E6B /* SWCrawlView.m */, 190 | D933DF571B0E165D00050E6B /* SWCrawlView.xib */, 191 | ); 192 | path = "Crawl View"; 193 | sourceTree = ""; 194 | }; 195 | D933DF6B1B0E18C700050E6B /* Logo Label */ = { 196 | isa = PBXGroup; 197 | children = ( 198 | D933DF6C1B0E18C700050E6B /* SWStrokedLogoLabel.h */, 199 | D933DF6D1B0E18C700050E6B /* SWStrokedLogoLabel.m */, 200 | ); 201 | name = "Logo Label"; 202 | path = BorderLabel; 203 | sourceTree = ""; 204 | }; 205 | D9A13BEC1B0E5483000ED3E7 /* Assets */ = { 206 | isa = PBXGroup; 207 | children = ( 208 | D9A13BED1B0E5483000ED3E7 /* Fonts */, 209 | D9A13BF51B0E5484000ED3E7 /* Images */, 210 | ); 211 | path = Assets; 212 | sourceTree = ""; 213 | }; 214 | D9A13BED1B0E5483000ED3E7 /* Fonts */ = { 215 | isa = PBXGroup; 216 | children = ( 217 | D9A13BEE1B0E5483000ED3E7 /* Franklin_Gothic_Book.ttf */, 218 | D9A13BEF1B0E5483000ED3E7 /* Star_Jedi_Rounded.ttf */, 219 | D9A13BF01B0E5483000ED3E7 /* Starjedi.ttf */, 220 | D9A13BF11B0E5483000ED3E7 /* StarJediBig.ttf */, 221 | D9A13BF21B0E5483000ED3E7 /* Starjhol.ttf */, 222 | D9A13BF31B0E5483000ED3E7 /* SWCrawlBody.ttf */, 223 | D9A13BF41B0E5484000ED3E7 /* SWCrawlTitle.ttf */, 224 | ); 225 | path = Fonts; 226 | sourceTree = ""; 227 | }; 228 | D9A13BF51B0E5484000ED3E7 /* Images */ = { 229 | isa = PBXGroup; 230 | children = ( 231 | D9A13BF61B0E5484000ED3E7 /* mask.png */, 232 | D9A13BF71B0E5484000ED3E7 /* starBg.png */, 233 | ); 234 | path = Images; 235 | sourceTree = ""; 236 | }; 237 | /* End PBXGroup section */ 238 | 239 | /* Begin PBXNativeTarget section */ 240 | D933DF231B0E155100050E6B /* SWCrawlViewExample */ = { 241 | isa = PBXNativeTarget; 242 | buildConfigurationList = D933DF471B0E155100050E6B /* Build configuration list for PBXNativeTarget "SWCrawlViewExample" */; 243 | buildPhases = ( 244 | D933DF201B0E155100050E6B /* Sources */, 245 | D933DF211B0E155100050E6B /* Frameworks */, 246 | D933DF221B0E155100050E6B /* Resources */, 247 | ); 248 | buildRules = ( 249 | ); 250 | dependencies = ( 251 | ); 252 | name = SWCrawlViewExample; 253 | productName = SWCrawlViewExample; 254 | productReference = D933DF241B0E155100050E6B /* SWCrawlViewExample.app */; 255 | productType = "com.apple.product-type.application"; 256 | }; 257 | D933DF3C1B0E155100050E6B /* SWCrawlViewExampleTests */ = { 258 | isa = PBXNativeTarget; 259 | buildConfigurationList = D933DF4A1B0E155100050E6B /* Build configuration list for PBXNativeTarget "SWCrawlViewExampleTests" */; 260 | buildPhases = ( 261 | D933DF391B0E155100050E6B /* Sources */, 262 | D933DF3A1B0E155100050E6B /* Frameworks */, 263 | D933DF3B1B0E155100050E6B /* Resources */, 264 | ); 265 | buildRules = ( 266 | ); 267 | dependencies = ( 268 | D933DF3F1B0E155100050E6B /* PBXTargetDependency */, 269 | ); 270 | name = SWCrawlViewExampleTests; 271 | productName = SWCrawlViewExampleTests; 272 | productReference = D933DF3D1B0E155100050E6B /* SWCrawlViewExampleTests.xctest */; 273 | productType = "com.apple.product-type.bundle.unit-test"; 274 | }; 275 | /* End PBXNativeTarget section */ 276 | 277 | /* Begin PBXProject section */ 278 | D933DF1C1B0E155100050E6B /* Project object */ = { 279 | isa = PBXProject; 280 | attributes = { 281 | LastUpgradeCheck = 0630; 282 | ORGANIZATIONNAME = "TJ Fallon"; 283 | TargetAttributes = { 284 | D933DF231B0E155100050E6B = { 285 | CreatedOnToolsVersion = 6.3; 286 | }; 287 | D933DF3C1B0E155100050E6B = { 288 | CreatedOnToolsVersion = 6.3; 289 | TestTargetID = D933DF231B0E155100050E6B; 290 | }; 291 | }; 292 | }; 293 | buildConfigurationList = D933DF1F1B0E155100050E6B /* Build configuration list for PBXProject "SWCrawlViewExample" */; 294 | compatibilityVersion = "Xcode 3.2"; 295 | developmentRegion = English; 296 | hasScannedForEncodings = 0; 297 | knownRegions = ( 298 | en, 299 | Base, 300 | ); 301 | mainGroup = D933DF1B1B0E155100050E6B; 302 | productRefGroup = D933DF251B0E155100050E6B /* Products */; 303 | projectDirPath = ""; 304 | projectRoot = ""; 305 | targets = ( 306 | D933DF231B0E155100050E6B /* SWCrawlViewExample */, 307 | D933DF3C1B0E155100050E6B /* SWCrawlViewExampleTests */, 308 | ); 309 | }; 310 | /* End PBXProject section */ 311 | 312 | /* Begin PBXResourcesBuildPhase section */ 313 | D933DF221B0E155100050E6B /* Resources */ = { 314 | isa = PBXResourcesBuildPhase; 315 | buildActionMask = 2147483647; 316 | files = ( 317 | D9A13BF91B0E5484000ED3E7 /* Star_Jedi_Rounded.ttf in Resources */, 318 | D933DF331B0E155100050E6B /* Main.storyboard in Resources */, 319 | D9A13C001B0E5484000ED3E7 /* starBg.png in Resources */, 320 | D933DF381B0E155100050E6B /* LaunchScreen.xib in Resources */, 321 | D9A13BFB1B0E5484000ED3E7 /* StarJediBig.ttf in Resources */, 322 | D9A13BFC1B0E5484000ED3E7 /* Starjhol.ttf in Resources */, 323 | D933DF5B1B0E165D00050E6B /* SWCrawlView.xib in Resources */, 324 | D9A13BFD1B0E5484000ED3E7 /* SWCrawlBody.ttf in Resources */, 325 | D9A13BF81B0E5484000ED3E7 /* Franklin_Gothic_Book.ttf in Resources */, 326 | D9A13BFA1B0E5484000ED3E7 /* Starjedi.ttf in Resources */, 327 | D933DF351B0E155100050E6B /* Images.xcassets in Resources */, 328 | D9A13BFE1B0E5484000ED3E7 /* SWCrawlTitle.ttf in Resources */, 329 | D9A13BFF1B0E5484000ED3E7 /* mask.png in Resources */, 330 | ); 331 | runOnlyForDeploymentPostprocessing = 0; 332 | }; 333 | D933DF3B1B0E155100050E6B /* Resources */ = { 334 | isa = PBXResourcesBuildPhase; 335 | buildActionMask = 2147483647; 336 | files = ( 337 | ); 338 | runOnlyForDeploymentPostprocessing = 0; 339 | }; 340 | /* End PBXResourcesBuildPhase section */ 341 | 342 | /* Begin PBXSourcesBuildPhase section */ 343 | D933DF201B0E155100050E6B /* Sources */ = { 344 | isa = PBXSourcesBuildPhase; 345 | buildActionMask = 2147483647; 346 | files = ( 347 | D933DF5A1B0E165D00050E6B /* SWCrawlView.m in Sources */, 348 | D933DF301B0E155100050E6B /* ViewController.m in Sources */, 349 | D933DF591B0E165D00050E6B /* SWCrawl.m in Sources */, 350 | D933DF2D1B0E155100050E6B /* AppDelegate.m in Sources */, 351 | D933DF2A1B0E155100050E6B /* main.m in Sources */, 352 | D933DF581B0E165D00050E6B /* SWConstants.m in Sources */, 353 | D933DF6E1B0E18C700050E6B /* SWStrokedLogoLabel.m in Sources */, 354 | ); 355 | runOnlyForDeploymentPostprocessing = 0; 356 | }; 357 | D933DF391B0E155100050E6B /* Sources */ = { 358 | isa = PBXSourcesBuildPhase; 359 | buildActionMask = 2147483647; 360 | files = ( 361 | D933DF441B0E155100050E6B /* SWCrawlViewExampleTests.m in Sources */, 362 | ); 363 | runOnlyForDeploymentPostprocessing = 0; 364 | }; 365 | /* End PBXSourcesBuildPhase section */ 366 | 367 | /* Begin PBXTargetDependency section */ 368 | D933DF3F1B0E155100050E6B /* PBXTargetDependency */ = { 369 | isa = PBXTargetDependency; 370 | target = D933DF231B0E155100050E6B /* SWCrawlViewExample */; 371 | targetProxy = D933DF3E1B0E155100050E6B /* PBXContainerItemProxy */; 372 | }; 373 | /* End PBXTargetDependency section */ 374 | 375 | /* Begin PBXVariantGroup section */ 376 | D933DF311B0E155100050E6B /* Main.storyboard */ = { 377 | isa = PBXVariantGroup; 378 | children = ( 379 | D933DF321B0E155100050E6B /* Base */, 380 | ); 381 | name = Main.storyboard; 382 | sourceTree = ""; 383 | }; 384 | D933DF361B0E155100050E6B /* LaunchScreen.xib */ = { 385 | isa = PBXVariantGroup; 386 | children = ( 387 | D933DF371B0E155100050E6B /* Base */, 388 | ); 389 | name = LaunchScreen.xib; 390 | sourceTree = ""; 391 | }; 392 | /* End PBXVariantGroup section */ 393 | 394 | /* Begin XCBuildConfiguration section */ 395 | D933DF451B0E155100050E6B /* Debug */ = { 396 | isa = XCBuildConfiguration; 397 | buildSettings = { 398 | ALWAYS_SEARCH_USER_PATHS = NO; 399 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 400 | CLANG_CXX_LIBRARY = "libc++"; 401 | CLANG_ENABLE_MODULES = YES; 402 | CLANG_ENABLE_OBJC_ARC = YES; 403 | CLANG_WARN_BOOL_CONVERSION = YES; 404 | CLANG_WARN_CONSTANT_CONVERSION = YES; 405 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 406 | CLANG_WARN_EMPTY_BODY = YES; 407 | CLANG_WARN_ENUM_CONVERSION = YES; 408 | CLANG_WARN_INT_CONVERSION = YES; 409 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 410 | CLANG_WARN_UNREACHABLE_CODE = YES; 411 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 412 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 413 | COPY_PHASE_STRIP = NO; 414 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 415 | ENABLE_STRICT_OBJC_MSGSEND = YES; 416 | GCC_C_LANGUAGE_STANDARD = gnu99; 417 | GCC_DYNAMIC_NO_PIC = NO; 418 | GCC_NO_COMMON_BLOCKS = YES; 419 | GCC_OPTIMIZATION_LEVEL = 0; 420 | GCC_PREPROCESSOR_DEFINITIONS = ( 421 | "DEBUG=1", 422 | "$(inherited)", 423 | ); 424 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 425 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 426 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 427 | GCC_WARN_UNDECLARED_SELECTOR = YES; 428 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 429 | GCC_WARN_UNUSED_FUNCTION = YES; 430 | GCC_WARN_UNUSED_VARIABLE = YES; 431 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 432 | MTL_ENABLE_DEBUG_INFO = YES; 433 | ONLY_ACTIVE_ARCH = YES; 434 | SDKROOT = iphoneos; 435 | TARGETED_DEVICE_FAMILY = "1,2"; 436 | }; 437 | name = Debug; 438 | }; 439 | D933DF461B0E155100050E6B /* Release */ = { 440 | isa = XCBuildConfiguration; 441 | buildSettings = { 442 | ALWAYS_SEARCH_USER_PATHS = NO; 443 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 444 | CLANG_CXX_LIBRARY = "libc++"; 445 | CLANG_ENABLE_MODULES = YES; 446 | CLANG_ENABLE_OBJC_ARC = YES; 447 | CLANG_WARN_BOOL_CONVERSION = YES; 448 | CLANG_WARN_CONSTANT_CONVERSION = YES; 449 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 450 | CLANG_WARN_EMPTY_BODY = YES; 451 | CLANG_WARN_ENUM_CONVERSION = YES; 452 | CLANG_WARN_INT_CONVERSION = YES; 453 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 454 | CLANG_WARN_UNREACHABLE_CODE = YES; 455 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 456 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 457 | COPY_PHASE_STRIP = NO; 458 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 459 | ENABLE_NS_ASSERTIONS = NO; 460 | ENABLE_STRICT_OBJC_MSGSEND = YES; 461 | GCC_C_LANGUAGE_STANDARD = gnu99; 462 | GCC_NO_COMMON_BLOCKS = YES; 463 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 464 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 465 | GCC_WARN_UNDECLARED_SELECTOR = YES; 466 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 467 | GCC_WARN_UNUSED_FUNCTION = YES; 468 | GCC_WARN_UNUSED_VARIABLE = YES; 469 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 470 | MTL_ENABLE_DEBUG_INFO = NO; 471 | SDKROOT = iphoneos; 472 | TARGETED_DEVICE_FAMILY = "1,2"; 473 | VALIDATE_PRODUCT = YES; 474 | }; 475 | name = Release; 476 | }; 477 | D933DF481B0E155100050E6B /* Debug */ = { 478 | isa = XCBuildConfiguration; 479 | buildSettings = { 480 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 481 | INFOPLIST_FILE = SWCrawlViewExample/Info.plist; 482 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 483 | PRODUCT_NAME = "$(TARGET_NAME)"; 484 | }; 485 | name = Debug; 486 | }; 487 | D933DF491B0E155100050E6B /* Release */ = { 488 | isa = XCBuildConfiguration; 489 | buildSettings = { 490 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 491 | INFOPLIST_FILE = SWCrawlViewExample/Info.plist; 492 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 493 | PRODUCT_NAME = "$(TARGET_NAME)"; 494 | }; 495 | name = Release; 496 | }; 497 | D933DF4B1B0E155100050E6B /* Debug */ = { 498 | isa = XCBuildConfiguration; 499 | buildSettings = { 500 | BUNDLE_LOADER = "$(TEST_HOST)"; 501 | FRAMEWORK_SEARCH_PATHS = ( 502 | "$(SDKROOT)/Developer/Library/Frameworks", 503 | "$(inherited)", 504 | ); 505 | GCC_PREPROCESSOR_DEFINITIONS = ( 506 | "DEBUG=1", 507 | "$(inherited)", 508 | ); 509 | INFOPLIST_FILE = SWCrawlViewExampleTests/Info.plist; 510 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 511 | PRODUCT_NAME = "$(TARGET_NAME)"; 512 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SWCrawlViewExample.app/SWCrawlViewExample"; 513 | }; 514 | name = Debug; 515 | }; 516 | D933DF4C1B0E155100050E6B /* Release */ = { 517 | isa = XCBuildConfiguration; 518 | buildSettings = { 519 | BUNDLE_LOADER = "$(TEST_HOST)"; 520 | FRAMEWORK_SEARCH_PATHS = ( 521 | "$(SDKROOT)/Developer/Library/Frameworks", 522 | "$(inherited)", 523 | ); 524 | INFOPLIST_FILE = SWCrawlViewExampleTests/Info.plist; 525 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 526 | PRODUCT_NAME = "$(TARGET_NAME)"; 527 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SWCrawlViewExample.app/SWCrawlViewExample"; 528 | }; 529 | name = Release; 530 | }; 531 | /* End XCBuildConfiguration section */ 532 | 533 | /* Begin XCConfigurationList section */ 534 | D933DF1F1B0E155100050E6B /* Build configuration list for PBXProject "SWCrawlViewExample" */ = { 535 | isa = XCConfigurationList; 536 | buildConfigurations = ( 537 | D933DF451B0E155100050E6B /* Debug */, 538 | D933DF461B0E155100050E6B /* Release */, 539 | ); 540 | defaultConfigurationIsVisible = 0; 541 | defaultConfigurationName = Release; 542 | }; 543 | D933DF471B0E155100050E6B /* Build configuration list for PBXNativeTarget "SWCrawlViewExample" */ = { 544 | isa = XCConfigurationList; 545 | buildConfigurations = ( 546 | D933DF481B0E155100050E6B /* Debug */, 547 | D933DF491B0E155100050E6B /* Release */, 548 | ); 549 | defaultConfigurationIsVisible = 0; 550 | defaultConfigurationName = Release; 551 | }; 552 | D933DF4A1B0E155100050E6B /* Build configuration list for PBXNativeTarget "SWCrawlViewExampleTests" */ = { 553 | isa = XCConfigurationList; 554 | buildConfigurations = ( 555 | D933DF4B1B0E155100050E6B /* Debug */, 556 | D933DF4C1B0E155100050E6B /* Release */, 557 | ); 558 | defaultConfigurationIsVisible = 0; 559 | defaultConfigurationName = Release; 560 | }; 561 | /* End XCConfigurationList section */ 562 | }; 563 | rootObject = D933DF1C1B0E155100050E6B /* Project object */; 564 | } 565 | --------------------------------------------------------------------------------