├── example ├── ViewPager │ ├── en.lproj │ │ ├── InfoPlist.strings │ │ ├── SGAnnotatedPagerController.xib │ │ └── SGViewPagerController.xib │ ├── ViewPagerExample-Prefix.pch │ ├── SGExampleController.h │ ├── SGAppDelegate.h │ ├── main.m │ ├── ViewPagerExample-Info.plist │ ├── SGExampleController.m │ └── SGAppDelegate.m └── ViewPagerExample.xcodeproj │ ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── simon.xcuserdatad │ │ └── WorkspaceSettings.xcsettings │ └── project.pbxproj ├── .gitignore ├── SGViewPagerController.h ├── SGAnnotatedPagerController.h ├── README.md ├── SGViewPagerController.m ├── SGAnnotatedPagerController.m ├── LICENSE.txt └── SGTabbedPager.swift /example/ViewPager/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /example/ViewPagerExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ViewPager/ViewPagerExample-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'ViewPager' target in the 'ViewPager' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_4_0 8 | #warning "This project uses features only available in iOS SDK 4.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /.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 | DerivedData 17 | .DS_Store 18 | 19 | # Thumbnails 20 | ._* 21 | 22 | # Files that might appear on external disk 23 | .Spotlight-V100 24 | .Trashes 25 | -------------------------------------------------------------------------------- /example/ViewPagerExample.xcodeproj/project.xcworkspace/xcuserdata/simon.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ViewPager/SGExampleController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SGViewController.h 3 | // ViewPager 4 | // 5 | // Copyright (c) 2012 Simon Grätzer 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #import 21 | 22 | @interface SGExampleController : UIViewController 23 | @end 24 | -------------------------------------------------------------------------------- /example/ViewPager/SGAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // SGAppDelegate.h 3 | // ViewPager 4 | // 5 | // Copyright (c) 2012 Simon Grätzer 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #import 21 | 22 | 23 | @interface SGAppDelegate : UIResponder 24 | 25 | @property (strong, nonatomic) UIWindow *window; 26 | 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /example/ViewPager/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ViewPager 4 | // 5 | // Copyright (c) 2012 Simon Grätzer 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #import 21 | 22 | #import "SGAppDelegate.h" 23 | 24 | int main(int argc, char *argv[]) 25 | { 26 | @autoreleasepool { 27 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([SGAppDelegate class])); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /SGViewPagerController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SGViewPagerController.h 3 | // SGViewPager 4 | // 5 | // Copyright (c) 2012-2015 Simon Grätzer 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #import 21 | 22 | @interface SGViewPagerController : UIViewController { 23 | BOOL _lockPageChange; 24 | } 25 | 26 | @property (readonly, nonatomic) UIPageControl *pageControl; 27 | @property (readonly, nonatomic) UIScrollView *scrollView; 28 | @property (nonatomic) NSUInteger pageIndex; 29 | 30 | - (void)reloadPages; 31 | - (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated;//TODO animations 32 | - (void)setPageIndex:(NSUInteger)index animated:(BOOL)animated; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /SGAnnotatedPagerController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SGViewController.h 3 | // SGViewPager 4 | // 5 | // Copyright (c) 2012-2015 Simon Grätzer 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #import "SGViewPagerController.h" 21 | 22 | @interface SGAnnotatedPagerController : UIViewController { 23 | NSUInteger _pageIndex; 24 | BOOL _lockPageChange; 25 | } 26 | 27 | @property (readonly, nonatomic) UIScrollView *titleScrollView; 28 | @property (readonly, nonatomic) UIScrollView *scrollView; 29 | @property (nonatomic) NSUInteger pageIndex; 30 | 31 | - (void)reloadPages; 32 | - (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated;//TODO animations 33 | - (void)setPageIndex:(NSUInteger)index animated:(BOOL)animated; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /example/ViewPager/ViewPagerExample-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | org.graetzer.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationPortraitUpsideDown 35 | UIInterfaceOrientationLandscapeLeft 36 | UIInterfaceOrientationLandscapeRight 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /example/ViewPager/SGExampleController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SGViewController.m 3 | // ViewPager 4 | // 5 | // Copyright (c) 2012 Simon Grätzer 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #import "SGExampleController.h" 21 | 22 | @interface SGExampleController () 23 | 24 | @end 25 | 26 | @implementation SGExampleController 27 | 28 | - (void)loadView { 29 | [super loadView]; 30 | 31 | self.view.autoresizesSubviews = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 32 | 33 | self.view.backgroundColor = [UIColor whiteColor]; 34 | NSString *text = [NSString stringWithFormat:@"Content of\n Controller %@", super.title]; 35 | 36 | UIFont *font = [UIFont boldSystemFontOfSize:25.0]; 37 | CGSize size = [@"Content of Controller" sizeWithFont:font]; 38 | CGRect frame = CGRectMake(0.5*(self.view.bounds.size.width - size.width), 39 | 0.5*(self.view.bounds.size.height - 3*size.height), size.width, 3*size.height); 40 | UILabel *l = [[UILabel alloc] initWithFrame:frame]; 41 | l.lineBreakMode = UILineBreakModeWordWrap; 42 | l.numberOfLines = 3; 43 | l.font = font; 44 | l.text = text; 45 | l.autoresizingMask = UIViewAutoresizingFlexibleTopMargin; 46 | [self.view addSubview:l]; 47 | } 48 | 49 | - (NSString *)title { 50 | return [NSString stringWithFormat:@"Title %@", super.title]; 51 | } 52 | 53 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 54 | { 55 | return YES; 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Description # 2 | SGViewPager contains custom UIViewController container, that display the content of child viewcontroller's in a paged scrollview. 3 | There are three implemenations, but the only recent one is [SGTabbedPager](https://github.com/graetzer/SGViewPager/blob/master/SGTabbedPager.swift) 4 | It is designed to look like the tabs in the android ActionBar and works really well for certain use cases. 5 | You can watch a [Demo video](http://youtu.be/IgrEA3FjGfs). 6 | It's written in swift and should be easy to customize. 7 | 8 | For example code look at my [MealPlanner App](https://github.com/graetzer/iOS-MensaPlanner) 9 | 10 | ------------------------- 11 | 12 | There are two more implementations, but they are not very recent. You will likely find the look outdated. 13 | - SGAnnotatedPagerController: Shows the title of child viewcontroller's at the top, slightly similar to the stream view in the Google+ App 14 | 15 | - SGViewPagerController: Display a UIPageControl at the bottom of the page 16 | 17 | # How to use these in your own project # 18 | Just copy either the SGAnnotatedPagerController.* files or the SGViewPagerController.* files in your XCode project. 19 | You don't have to load the viewcontrollers from a xib or a storyboard file, just make sure that the view 20 | has an appropriate size if you use a UINavigationController (416px) or a UITabBarController(411px). 21 | 22 | # Example code # 23 | SGAnnotatedPagerController *annotated = [[SGAnnotatedPagerController alloc]initWithNibName:@"SGAnnotatedPagerController" bundle:nil]; 24 | annotated.title = @"TitleControl"; 25 | for (int i = 0; i < 5; i++) { 26 | SGExampleController *ec = [[SGExampleController alloc] init]; 27 | ec.title = [NSString stringWithFormat:@"Nr. %d", i+1]; 28 | [annotated addPage:ec]; 29 | } 30 | self.window.rootViewController = annotated; 31 | // ... 32 | 33 | 34 | For detailed example code look in the SGAppDelegate.m file in the example project 35 | 36 | # Licence # 37 | Copyright (c) 2012 Simon Grätzer 38 | 39 | Licensed under the Apache License, Version 2.0 (the "License"); 40 | you may not use this file except in compliance with the License. 41 | You may obtain a copy of the License at 42 | 43 | http://www.apache.org/licenses/LICENSE-2.0 44 | 45 | Unless required by applicable law or agreed to in writing, software 46 | distributed under the License is distributed on an "AS IS" BASIS, 47 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 48 | See the License for the specific language governing permissions and 49 | limitations under the License. 50 | -------------------------------------------------------------------------------- /example/ViewPager/SGAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // SGAppDelegate.m 3 | // ViewPager 4 | // 5 | // Copyright (c) 2012 Simon Grätzer 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #import "SGAppDelegate.h" 21 | 22 | #import "SGExampleController.h" 23 | #import "SGViewPagerController.h" 24 | #import "SGAnnotatedPagerController.h" 25 | 26 | @implementation SGAppDelegate 27 | 28 | @synthesize window = _window; 29 | 30 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 31 | { 32 | // The xib files are used to create views with a height adjusted to an UITabBarController 33 | SGViewPagerController *pager = [[SGViewPagerController alloc] initWithNibName:@"SGViewPagerController" bundle:nil]; 34 | pager.title = @"UIPageControl"; 35 | 36 | NSMutableArray *array = [NSMutableArray arrayWithCapacity:5]; 37 | for (int i = 0; i < 5; i++) { 38 | SGExampleController *ec = [[SGExampleController alloc] init]; 39 | ec.title = [NSString stringWithFormat:@"Nr. %d", i+1]; 40 | [array addObject:ec]; 41 | } 42 | [pager setViewControllers:array animated:NO]; 43 | 44 | SGAnnotatedPagerController *annotatedPager = [[SGAnnotatedPagerController alloc] initWithNibName:@"SGAnnotatedPagerController" bundle:nil]; 45 | annotatedPager.title = @"TitleControl"; 46 | 47 | [array removeAllObjects]; 48 | for (int i = 0; i < 5; i++) { 49 | SGExampleController *ec = [[SGExampleController alloc] init]; 50 | ec.title = [NSString stringWithFormat:@"Nr. %d", i+1]; 51 | [array addObject:ec]; 52 | } 53 | [annotatedPager setViewControllers:array animated:NO]; 54 | 55 | UITabBarController *tabC = [[UITabBarController alloc] init]; 56 | [tabC setViewControllers:[NSArray arrayWithObjects:pager, annotatedPager, nil] animated:NO]; 57 | 58 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 59 | self.window.rootViewController = tabC; 60 | [self.window makeKeyAndVisible]; 61 | return YES; 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /example/ViewPager/en.lproj/SGAnnotatedPagerController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1296 5 | 11D50 6 | 2182 7 | 1138.32 8 | 568.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 1181 12 | 13 | 14 | IBProxyObject 15 | IBUIView 16 | 17 | 18 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 19 | 20 | 21 | PluginDependencyRecalculationVersion 22 | 23 | 24 | 25 | 26 | IBFilesOwner 27 | IBCocoaTouchFramework 28 | 29 | 30 | IBFirstResponder 31 | IBCocoaTouchFramework 32 | 33 | 34 | 35 | 274 36 | {{0, 20}, {320, 411}} 37 | 38 | 39 | 40 | 1 41 | MCAxIDAAA 42 | 43 | NO 44 | 45 | 46 | IBCocoaTouchFramework 47 | 48 | 49 | 50 | 51 | 52 | 53 | view 54 | 55 | 56 | 57 | 7 58 | 59 | 60 | 61 | 62 | 63 | 0 64 | 65 | 66 | 67 | 68 | 69 | -1 70 | 71 | 72 | File's Owner 73 | 74 | 75 | -2 76 | 77 | 78 | 79 | 80 | 6 81 | 82 | 83 | 84 | 85 | 86 | 87 | SGAnnotatedPagerController 88 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 89 | UIResponder 90 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 91 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 92 | 93 | 94 | 95 | 96 | 97 | 13 98 | 99 | 100 | 101 | 102 | SGAnnotatedPagerController 103 | UIViewController 104 | 105 | IBProjectSource 106 | ./Classes/SGAnnotatedPagerController.h 107 | 108 | 109 | 110 | 111 | 0 112 | IBCocoaTouchFramework 113 | 114 | com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS 115 | 116 | 117 | YES 118 | 3 119 | 1181 120 | 121 | 122 | -------------------------------------------------------------------------------- /example/ViewPager/en.lproj/SGViewPagerController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1296 5 | 11D50 6 | 2182 7 | 1138.32 8 | 568.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 1181 12 | 13 | 14 | IBProxyObject 15 | IBUIView 16 | 17 | 18 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 19 | 20 | 21 | PluginDependencyRecalculationVersion 22 | 23 | 24 | 25 | 26 | IBFilesOwner 27 | IBCocoaTouchFramework 28 | 29 | 30 | IBFirstResponder 31 | IBCocoaTouchFramework 32 | 33 | 34 | 35 | 274 36 | {{0, 20}, {320, 411}} 37 | 38 | 39 | 40 | 1 41 | MC4xODM4MzI5NzgzIDAuODU4Njk1NjUyMiAwLjEzODA0OTIzOTEAA 42 | 43 | NO 44 | 45 | 46 | IBCocoaTouchFramework 47 | 48 | 49 | 50 | 51 | 52 | 53 | view 54 | 55 | 56 | 57 | 7 58 | 59 | 60 | 61 | 62 | 63 | 0 64 | 65 | 66 | 67 | 68 | 69 | -1 70 | 71 | 72 | File's Owner 73 | 74 | 75 | -2 76 | 77 | 78 | 79 | 80 | 6 81 | 82 | 83 | 84 | 85 | 86 | 87 | SGViewPagerController 88 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 89 | UIResponder 90 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 91 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 92 | 93 | 94 | 95 | 96 | 97 | 13 98 | 99 | 100 | 101 | 102 | SGViewPagerController 103 | UIViewController 104 | 105 | IBProjectSource 106 | ./Classes/SGViewPagerController.h 107 | 108 | 109 | 110 | 111 | 0 112 | IBCocoaTouchFramework 113 | 114 | com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS 115 | 116 | 117 | YES 118 | 3 119 | 1181 120 | 121 | 122 | -------------------------------------------------------------------------------- /SGViewPagerController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SGViewPagerController.m 3 | // SGViewPager 4 | // 5 | // Copyright (c) 2012 Simon Grätzer 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #import "SGViewPagerController.h" 21 | 22 | #define PAGE_CONTROL_HEIGHT 20.0 23 | 24 | @interface SGViewPagerController () 25 | 26 | @end 27 | 28 | @implementation SGViewPagerController 29 | @synthesize scrollView, pageControl; 30 | @dynamic pageIndex; 31 | 32 | - (void)loadView { 33 | [super loadView]; 34 | self.view.backgroundColor = [UIColor lightGrayColor]; 35 | 36 | CGRect frame = CGRectMake(0, self.view.bounds.size.height - PAGE_CONTROL_HEIGHT, 37 | self.view.bounds.size.width, PAGE_CONTROL_HEIGHT); 38 | pageControl = [[UIPageControl alloc] initWithFrame:frame]; 39 | pageControl.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin | 40 | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin; 41 | self.pageControl.backgroundColor = [UIColor blackColor]; 42 | [pageControl addTarget:self action:@selector(changePage:) forControlEvents:UIControlEventValueChanged]; 43 | 44 | frame = CGRectMake(0, 0, self.view.bounds.size.width, 45 | self.view.bounds.size.height-PAGE_CONTROL_HEIGHT); 46 | scrollView = [[UIScrollView alloc] initWithFrame:frame]; 47 | scrollView.delegate = self; 48 | scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | 49 | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; 50 | scrollView.autoresizesSubviews = YES; 51 | scrollView.backgroundColor = [UIColor clearColor]; 52 | scrollView.canCancelContentTouches = NO; 53 | scrollView.showsHorizontalScrollIndicator = NO; 54 | scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite; 55 | scrollView.clipsToBounds = YES; 56 | scrollView.scrollEnabled = YES; 57 | scrollView.pagingEnabled = YES; 58 | 59 | [self.view addSubview:scrollView]; 60 | [self.view addSubview:pageControl]; 61 | } 62 | 63 | - (void)viewDidLoad 64 | { 65 | [super viewDidLoad]; 66 | [self reloadPages]; 67 | } 68 | 69 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 70 | { 71 | return YES; 72 | } 73 | 74 | - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration { 75 | _lockPageChange = YES; //The scrollview tends to scroll to a different page when the screen rotates 76 | [self reloadPages]; 77 | } 78 | 79 | - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { 80 | _lockPageChange = NO; 81 | [self setPageIndex:self.pageIndex animated:NO]; 82 | } 83 | 84 | #pragma mark Add and remove 85 | - (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated { 86 | if (self.childViewControllers.count > 0) { 87 | self.pageIndex = 0; 88 | for (UIViewController *vC in self.childViewControllers) { 89 | [vC willMoveToParentViewController:nil]; 90 | [vC removeFromParentViewController]; 91 | } 92 | } 93 | 94 | for (UIViewController *vC in viewControllers) { 95 | [self addChildViewController:vC]; 96 | [vC didMoveToParentViewController:self]; 97 | } 98 | if (self.scrollView) 99 | [self reloadPages]; 100 | //TODO animations 101 | } 102 | 103 | 104 | 105 | #pragma mark Properties 106 | - (void)setPageIndex:(NSUInteger)pageIndex { 107 | [self setPageIndex:pageIndex animated:NO]; 108 | } 109 | 110 | - (void)setPageIndex:(NSUInteger)index animated:(BOOL)animated; { 111 | 112 | pageControl.currentPage = index; 113 | /* 114 | * Change the scroll view 115 | */ 116 | CGRect frame = scrollView.frame; 117 | frame.origin.x = frame.size.width * index; 118 | frame.origin.y = 0; 119 | 120 | if (frame.origin.x < scrollView.contentSize.width) { 121 | [scrollView scrollRectToVisible:frame animated:animated]; 122 | /* 123 | * When the animated scrolling finishings, scrollViewDidEndDecelerating will turn this off 124 | */ 125 | _lockPageChange = YES; 126 | } 127 | } 128 | 129 | - (NSUInteger)pageIndex { 130 | return self.pageControl.currentPage; 131 | } 132 | 133 | #pragma mark - 134 | #pragma mark UIScrollViewDelegate stuff 135 | - (void)scrollViewDidScroll:(UIScrollView *)_scrollView 136 | { 137 | if (_lockPageChange) 138 | return; 139 | /* 140 | * We switch page at 50% across 141 | */ 142 | CGFloat pageWidth = _scrollView.frame.size.width; 143 | int page = floor((_scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1; 144 | 145 | pageControl.currentPage = page; 146 | } 147 | 148 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)_scrollView 149 | { 150 | _lockPageChange = NO; 151 | } 152 | 153 | - (void)reloadPages { 154 | for (UIView *view in scrollView.subviews) { 155 | [view removeFromSuperview]; 156 | } 157 | 158 | CGFloat cx = 0; 159 | NSUInteger count = self.childViewControllers.count; 160 | for (NSUInteger i = 0; i < count; i++) { 161 | UIView *view = [[self.childViewControllers objectAtIndex:i] view]; 162 | CGRect rect = view.frame; 163 | 164 | rect.origin.x = cx; 165 | rect.origin.y = 0; 166 | view.frame = rect; 167 | 168 | [scrollView addSubview:view]; 169 | 170 | cx += scrollView.frame.size.width; 171 | } 172 | 173 | self.pageControl.numberOfPages = count; 174 | [scrollView setContentSize:CGSizeMake(cx, [scrollView bounds].size.height)]; 175 | } 176 | 177 | #pragma mark - 178 | #pragma mark PageControl stuff 179 | - (IBAction)changePage:(id)sender 180 | { 181 | /* 182 | * Change the scroll view 183 | */ 184 | CGRect frame = scrollView.frame; 185 | frame.origin.x = frame.size.width * pageControl.currentPage; 186 | frame.origin.y = 0; 187 | 188 | [scrollView scrollRectToVisible:frame animated:YES]; 189 | 190 | /* 191 | * When the animated scrolling finishings, scrollViewDidEndDecelerating will turn this off 192 | */ 193 | _lockPageChange = YES; 194 | } 195 | 196 | @end 197 | -------------------------------------------------------------------------------- /SGAnnotatedPagerController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SGViewController.m 3 | // SGViewPager 4 | // 5 | // Copyright (c) 2012-2015 Simon Grätzer 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #import "SGAnnotatedPagerController.h" 21 | 22 | #define TITLE_CONTROL_HEIGHT 25.0 23 | 24 | @interface SGAnnotatedPagerController () 25 | 26 | @end 27 | 28 | @implementation SGAnnotatedPagerController 29 | @synthesize scrollView, titleScrollView; 30 | @dynamic pageIndex; 31 | 32 | - (void)loadView { 33 | [super loadView]; 34 | self.view.backgroundColor = [UIColor lightGrayColor]; 35 | 36 | CGRect frame = CGRectMake(0, 0, self.view.bounds.size.width, TITLE_CONTROL_HEIGHT); 37 | titleScrollView = [[UIScrollView alloc] initWithFrame:frame]; 38 | titleScrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; 39 | titleScrollView.backgroundColor = [UIColor lightGrayColor]; 40 | [titleScrollView setCanCancelContentTouches:NO]; 41 | titleScrollView.showsHorizontalScrollIndicator = NO; 42 | titleScrollView.clipsToBounds = YES; 43 | titleScrollView.scrollEnabled = YES; 44 | titleScrollView.userInteractionEnabled = NO; 45 | 46 | frame = CGRectMake(0, TITLE_CONTROL_HEIGHT, self.view.bounds.size.width, 47 | self.view.bounds.size.height - TITLE_CONTROL_HEIGHT); 48 | scrollView = [[UIScrollView alloc] initWithFrame:frame]; 49 | scrollView.delegate = self; 50 | scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | 51 | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; 52 | scrollView.autoresizesSubviews = YES; 53 | scrollView.backgroundColor = [UIColor clearColor]; 54 | scrollView.canCancelContentTouches = NO; 55 | scrollView.showsHorizontalScrollIndicator = NO; 56 | scrollView.clipsToBounds = YES; 57 | scrollView.scrollEnabled = YES; 58 | scrollView.pagingEnabled = YES; 59 | 60 | [self.view addSubview:scrollView]; 61 | [self.view addSubview:titleScrollView]; 62 | [self reloadPages]; 63 | } 64 | 65 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 66 | { 67 | return YES; 68 | } 69 | 70 | - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration { 71 | _lockPageChange = YES; 72 | [self reloadPages]; 73 | } 74 | 75 | - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { 76 | _lockPageChange = NO; 77 | [self setPageIndex:self.pageIndex animated:NO]; 78 | } 79 | 80 | #pragma mark Add and remove 81 | - (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated { 82 | if (self.childViewControllers.count > 0) { 83 | self.pageIndex = 0; 84 | for (UIViewController *vC in self.childViewControllers) { 85 | [vC willMoveToParentViewController:nil]; 86 | [vC removeFromParentViewController]; 87 | } 88 | } 89 | 90 | for (UIViewController *vC in viewControllers) { 91 | [self addChildViewController:vC]; 92 | [vC didMoveToParentViewController:self]; 93 | } 94 | if (self.scrollView) 95 | [self reloadPages]; 96 | //TODO animations 97 | } 98 | 99 | #pragma mark Properties 100 | - (void)setPageIndex:(NSUInteger)pageIndex { 101 | [self setPageIndex:pageIndex animated:NO]; 102 | } 103 | 104 | - (void)setPageIndex:(NSUInteger)index animated:(BOOL)animated; { 105 | _pageIndex = index; 106 | /* 107 | * Change the scroll view 108 | */ 109 | CGRect frame = scrollView.frame; 110 | frame.origin.x = frame.size.width * index; 111 | frame.origin.y = 0; 112 | 113 | if (frame.origin.x < scrollView.contentSize.width) { 114 | [scrollView scrollRectToVisible:frame animated:animated]; 115 | } 116 | } 117 | 118 | - (NSUInteger)pageIndex { 119 | return _pageIndex; 120 | } 121 | 122 | #pragma mark - 123 | #pragma mark UIScrollViewDelegate stuff 124 | - (void)scrollViewDidScroll:(UIScrollView *)_scrollView 125 | { 126 | //The scrollview tends to scroll to a different page when the screen rotates 127 | if (_lockPageChange) 128 | return; 129 | 130 | CGFloat newXOff = (_scrollView.contentOffset.x/_scrollView.contentSize.width) 131 | *0.5*titleScrollView.bounds.size.width*self.childViewControllers.count; 132 | titleScrollView.contentOffset = CGPointMake(newXOff, 0); 133 | 134 | /* 135 | * We switch page at 50% across 136 | */ 137 | CGFloat pageWidth = _scrollView.frame.size.width; 138 | int page = floor((_scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1; 139 | _pageIndex = page; 140 | } 141 | 142 | - (void)reloadPages { 143 | for (UIView *view in titleScrollView.subviews) { 144 | [view removeFromSuperview]; 145 | } 146 | for (UIView *view in scrollView.subviews) { 147 | [view removeFromSuperview]; 148 | } 149 | 150 | CGFloat cx = 0; 151 | CGFloat titleItemWidth = titleScrollView.bounds.size.width/2; 152 | CGFloat dx = titleItemWidth/2; 153 | 154 | NSUInteger count = self.childViewControllers.count; 155 | for (NSUInteger i = 0; i < count; i++) { 156 | UIViewController *vC = [self.childViewControllers objectAtIndex:i]; 157 | 158 | CGRect frame = CGRectMake(dx, 0, titleItemWidth, titleScrollView.bounds.size.height); 159 | UIView *view = [[UIView alloc]initWithFrame:frame]; 160 | view.autoresizingMask = UIViewAutoresizingFlexibleWidth; 161 | view.backgroundColor = [UIColor lightGrayColor]; 162 | UIFont *font = [UIFont boldSystemFontOfSize:15.0]; 163 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_0 164 | CGSize size = [vC.title sizeWithAttributes:@{NSFontAttributeName:font}]; 165 | #else 166 | CGSize size = [vC.title sizeWithFont:font]; 167 | #endif 168 | frame = CGRectMake(0.5*(frame.size.width - size.width), 169 | 0.5*(frame.size.height - size.height), size.width, size.height); 170 | UILabel *l = [[UILabel alloc] initWithFrame:frame]; 171 | l.backgroundColor = [UIColor clearColor]; 172 | l.font = font; 173 | l.text = vC.title; 174 | [view addSubview:l]; 175 | [titleScrollView addSubview:view]; 176 | dx += titleItemWidth; 177 | 178 | view = vC.view; 179 | CGRect rect = view.frame; 180 | rect.origin.x = cx; 181 | rect.origin.y = 0; 182 | view.frame = rect; 183 | [scrollView addSubview:view]; 184 | cx += scrollView.frame.size.width; 185 | } 186 | [titleScrollView setContentSize:CGSizeMake(dx+titleItemWidth/2, titleScrollView.bounds.size.height)]; 187 | [scrollView setContentSize:CGSizeMake(cx, scrollView.bounds.size.height)]; 188 | } 189 | 190 | @end 191 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /SGTabbedPager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SGTabbedPager.swift 3 | // SGViewPager 4 | // 5 | // Copyright (c) 2012-2015 Simon Grätzer 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | import UIKit 21 | 22 | public protocol SGTabbedPagerDatasource { 23 | func numberOfViewControllers() -> Int 24 | func viewController(page:Int) -> UIViewController 25 | func viewControllerTitle(page:Int) -> String 26 | } 27 | 28 | public protocol SGTabbedPagerDelegate { 29 | //func willShowViewController(page:Int) -> Void 30 | func didShowViewController(page:Int) -> Void 31 | } 32 | 33 | public class SGTabbedPager: UIViewController, UIScrollViewDelegate { 34 | 35 | public var datasource : SGTabbedPagerDatasource? = nil 36 | public var delegate : SGTabbedPagerDelegate? = nil 37 | 38 | private let tabHeight = CGFloat(44); 39 | private var titleScrollView, contentScrollView : UIScrollView! 40 | private var viewControllers = [UIViewController]() 41 | private var viewControllerCount : Int = 0 42 | private var tabButtons = [UIButton]() 43 | private var bottomLine, tabIndicator : UIView! 44 | private var selectedIndex : Int = 0 45 | private var enableParallex = true 46 | 47 | public var selectedViewController : UIViewController { 48 | get { 49 | return viewControllers[selectedIndex] 50 | } 51 | } 52 | public var tabColor : UIColor = UIColor(red: 0, green: 0.329, blue: 0.624, alpha: 1) { 53 | didSet { 54 | if bottomLine != nil { 55 | bottomLine.backgroundColor = tabColor 56 | } 57 | if tabIndicator != nil { 58 | tabIndicator.backgroundColor = tabColor 59 | } 60 | } 61 | } 62 | 63 | // MARK: View Controller state restauration 64 | public override func encodeRestorableStateWithCoder(coder: NSCoder) { 65 | super.encodeRestorableStateWithCoder(coder) 66 | coder.encodeInteger(selectedIndex, forKey: "selectedIndex") 67 | } 68 | 69 | public override func decodeRestorableStateWithCoder(coder: NSCoder) { 70 | super.decodeRestorableStateWithCoder(coder) 71 | selectedIndex = coder.decodeIntegerForKey("selectedIndex") 72 | } 73 | 74 | public override func loadView() { 75 | super.loadView() 76 | titleScrollView = UIScrollView(frame: CGRectZero) 77 | titleScrollView.translatesAutoresizingMaskIntoConstraints = false 78 | titleScrollView.autoresizingMask = [.FlexibleWidth, .FlexibleBottomMargin] 79 | titleScrollView.backgroundColor = UIColor.whiteColor() 80 | titleScrollView.canCancelContentTouches = false 81 | titleScrollView.showsHorizontalScrollIndicator = false 82 | titleScrollView.bounces = false 83 | titleScrollView.delegate = self 84 | self.view.addSubview(titleScrollView) 85 | 86 | bottomLine = UIView(frame: CGRectZero) 87 | bottomLine.backgroundColor = tabColor 88 | titleScrollView.addSubview(bottomLine) 89 | tabIndicator = UIView(frame: CGRectZero) 90 | tabIndicator.backgroundColor = tabColor 91 | titleScrollView.addSubview(tabIndicator) 92 | 93 | contentScrollView = UIScrollView(frame: CGRectZero) 94 | contentScrollView.translatesAutoresizingMaskIntoConstraints = false 95 | contentScrollView.autoresizingMask = [.FlexibleWidth, .FlexibleBottomMargin] 96 | contentScrollView.backgroundColor = UIColor.whiteColor() 97 | contentScrollView.delaysContentTouches = false 98 | contentScrollView.showsHorizontalScrollIndicator = false 99 | contentScrollView.pagingEnabled = true 100 | contentScrollView.scrollEnabled = true 101 | contentScrollView.delegate = self 102 | self.view.addSubview(contentScrollView) 103 | } 104 | 105 | public override func viewWillAppear(animated: Bool) { 106 | super.viewWillAppear(animated) 107 | self.reloadData() 108 | } 109 | 110 | public override func viewWillLayoutSubviews() { 111 | self.layout() 112 | } 113 | 114 | public override func willTransitionToTraitCollection(newCollection: UITraitCollection, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { 115 | if titleScrollView != nil { 116 | titleScrollView.delegate = nil 117 | contentScrollView.delegate = nil 118 | coordinator.animateAlongsideTransition(nil, completion: {_ -> Void in 119 | self.titleScrollView.delegate = self 120 | self.contentScrollView.delegate = self 121 | self.switchPage(self.selectedIndex, animated: false) 122 | }) 123 | } 124 | } 125 | 126 | // MARK: Public methods 127 | public func reloadData() { 128 | for vc in viewControllers { 129 | vc.willMoveToParentViewController(nil) 130 | vc.view.removeFromSuperview() 131 | vc.removeFromParentViewController() 132 | } 133 | viewControllers.removeAll(keepCapacity: true) 134 | 135 | if let cc = datasource?.numberOfViewControllers() { 136 | self.viewControllerCount = cc 137 | for i in 0.. 0 {// Happens for example in case of a restore 153 | switchPage(selectedIndex, animated: false) 154 | } 155 | } 156 | } 157 | 158 | public func switchPage(index :Int, animated : Bool) { 159 | let frame = CGRectMake(contentScrollView.frame.size.width * CGFloat(index), 0, 160 | contentScrollView.frame.size.width, contentScrollView.frame.size.height) ; 161 | if frame.origin.x < contentScrollView.contentSize.width { 162 | // It doesn't look good if the tab's jump back and then gets animated back 163 | // by the code inside 'scrollViewDidScroll', but we only need to 164 | // disable parallax if scrollViewDidEndScrollingAnimation is gonna be called afterwards 165 | enableParallex = !animated 166 | 167 | var point = tabButtons[index].frame.origin 168 | point.x -= (titleScrollView.bounds.size.width - tabButtons[index].frame.size.width)/2 169 | titleScrollView.setContentOffset(point, animated: animated) 170 | contentScrollView.scrollRectToVisible(frame, animated: animated) 171 | } 172 | } 173 | 174 | // MARK: Helpers methods 175 | /// Generate the fitting UILabel's 176 | private func generateTabs() { 177 | for label in self.tabButtons { 178 | label.removeFromSuperview() 179 | } 180 | self.tabButtons.removeAll(keepCapacity: true) 181 | 182 | let font = UIFont(name: "HelveticaNeue-Thin", size: 20) 183 | for i in 0.. 0.4344 263 | let newXOff = tabButtons[index].frame.origin.x + diff * frac - centering1 * (1-frac) - centering2 * frac; 264 | titleScrollView.contentOffset = CGPointMake(fmax(0, newXOff), 0) 265 | } 266 | } 267 | } 268 | 269 | /// Since it looks better, we disable the parralel movement effect on the title scrollview 270 | /// before we do a scroll animation 271 | public func scrollViewDidEndScrollingAnimation(scrollView: UIScrollView) { 272 | if scrollView == contentScrollView { 273 | enableParallex = true// Always enable after an animation 274 | } 275 | } 276 | } -------------------------------------------------------------------------------- /example/ViewPagerExample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | F40AE30C15297F1800F7C596 /* SGAnnotatedPagerController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F40AE30A15297F1800F7C596 /* SGAnnotatedPagerController.xib */; }; 11 | F44D9CC015261759003D3E8F /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F44D9CBF15261759003D3E8F /* UIKit.framework */; }; 12 | F44D9CC215261759003D3E8F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F44D9CC115261759003D3E8F /* Foundation.framework */; }; 13 | F44D9CC415261759003D3E8F /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F44D9CC315261759003D3E8F /* CoreGraphics.framework */; }; 14 | F44D9CCA15261759003D3E8F /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F44D9CC815261759003D3E8F /* InfoPlist.strings */; }; 15 | F44D9CCC15261759003D3E8F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F44D9CCB15261759003D3E8F /* main.m */; }; 16 | F44D9CD015261759003D3E8F /* SGAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F44D9CCF15261759003D3E8F /* SGAppDelegate.m */; }; 17 | F44D9CD315261759003D3E8F /* SGExampleController.m in Sources */ = {isa = PBXBuildFile; fileRef = F44D9CD215261759003D3E8F /* SGExampleController.m */; }; 18 | F44D9CD615261759003D3E8F /* SGViewPagerController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F44D9CD415261759003D3E8F /* SGViewPagerController.xib */; }; 19 | F48B41A31529BEB100931141 /* SGAnnotatedPagerController.m in Sources */ = {isa = PBXBuildFile; fileRef = F48B41A01529BEB100931141 /* SGAnnotatedPagerController.m */; }; 20 | F48B41A41529BEB100931141 /* SGViewPagerController.m in Sources */ = {isa = PBXBuildFile; fileRef = F48B41A21529BEB100931141 /* SGViewPagerController.m */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXFileReference section */ 24 | F40AE30B15297F1800F7C596 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/SGAnnotatedPagerController.xib; sourceTree = ""; }; 25 | F44D9CBB15261759003D3E8F /* ViewPagerExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ViewPagerExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 26 | F44D9CBF15261759003D3E8F /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 27 | F44D9CC115261759003D3E8F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 28 | F44D9CC315261759003D3E8F /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 29 | F44D9CC715261759003D3E8F /* ViewPagerExample-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ViewPagerExample-Info.plist"; sourceTree = ""; }; 30 | F44D9CC915261759003D3E8F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 31 | F44D9CCB15261759003D3E8F /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 32 | F44D9CCD15261759003D3E8F /* ViewPagerExample-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ViewPagerExample-Prefix.pch"; sourceTree = ""; }; 33 | F44D9CCE15261759003D3E8F /* SGAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SGAppDelegate.h; sourceTree = ""; }; 34 | F44D9CCF15261759003D3E8F /* SGAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SGAppDelegate.m; sourceTree = ""; }; 35 | F44D9CD115261759003D3E8F /* SGExampleController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SGExampleController.h; sourceTree = ""; }; 36 | F44D9CD215261759003D3E8F /* SGExampleController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SGExampleController.m; sourceTree = ""; }; 37 | F44D9CD515261759003D3E8F /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/SGViewPagerController.xib; sourceTree = ""; }; 38 | F48B419F1529BEB100931141 /* SGAnnotatedPagerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SGAnnotatedPagerController.h; path = ../SGAnnotatedPagerController.h; sourceTree = ""; }; 39 | F48B41A01529BEB100931141 /* SGAnnotatedPagerController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SGAnnotatedPagerController.m; path = ../SGAnnotatedPagerController.m; sourceTree = ""; }; 40 | F48B41A11529BEB100931141 /* SGViewPagerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SGViewPagerController.h; path = ../SGViewPagerController.h; sourceTree = ""; }; 41 | F48B41A21529BEB100931141 /* SGViewPagerController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SGViewPagerController.m; path = ../SGViewPagerController.m; sourceTree = ""; }; 42 | /* End PBXFileReference section */ 43 | 44 | /* Begin PBXFrameworksBuildPhase section */ 45 | F44D9CB815261759003D3E8F /* Frameworks */ = { 46 | isa = PBXFrameworksBuildPhase; 47 | buildActionMask = 2147483647; 48 | files = ( 49 | F44D9CC015261759003D3E8F /* UIKit.framework in Frameworks */, 50 | F44D9CC215261759003D3E8F /* Foundation.framework in Frameworks */, 51 | F44D9CC415261759003D3E8F /* CoreGraphics.framework in Frameworks */, 52 | ); 53 | runOnlyForDeploymentPostprocessing = 0; 54 | }; 55 | /* End PBXFrameworksBuildPhase section */ 56 | 57 | /* Begin PBXGroup section */ 58 | F44D9CB015261759003D3E8F = { 59 | isa = PBXGroup; 60 | children = ( 61 | F48B419F1529BEB100931141 /* SGAnnotatedPagerController.h */, 62 | F48B41A01529BEB100931141 /* SGAnnotatedPagerController.m */, 63 | F48B41A11529BEB100931141 /* SGViewPagerController.h */, 64 | F48B41A21529BEB100931141 /* SGViewPagerController.m */, 65 | F44D9CC515261759003D3E8F /* ViewPagerExample */, 66 | F44D9CBE15261759003D3E8F /* Frameworks */, 67 | F44D9CBC15261759003D3E8F /* Products */, 68 | ); 69 | sourceTree = ""; 70 | }; 71 | F44D9CBC15261759003D3E8F /* Products */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | F44D9CBB15261759003D3E8F /* ViewPagerExample.app */, 75 | ); 76 | name = Products; 77 | sourceTree = ""; 78 | }; 79 | F44D9CBE15261759003D3E8F /* Frameworks */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | F44D9CBF15261759003D3E8F /* UIKit.framework */, 83 | F44D9CC115261759003D3E8F /* Foundation.framework */, 84 | F44D9CC315261759003D3E8F /* CoreGraphics.framework */, 85 | ); 86 | name = Frameworks; 87 | sourceTree = ""; 88 | }; 89 | F44D9CC515261759003D3E8F /* ViewPagerExample */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | F40AE30A15297F1800F7C596 /* SGAnnotatedPagerController.xib */, 93 | F44D9CCE15261759003D3E8F /* SGAppDelegate.h */, 94 | F44D9CCF15261759003D3E8F /* SGAppDelegate.m */, 95 | F44D9CD115261759003D3E8F /* SGExampleController.h */, 96 | F44D9CD215261759003D3E8F /* SGExampleController.m */, 97 | F44D9CD415261759003D3E8F /* SGViewPagerController.xib */, 98 | F44D9CC615261759003D3E8F /* Supporting Files */, 99 | ); 100 | name = ViewPagerExample; 101 | path = ViewPager; 102 | sourceTree = ""; 103 | }; 104 | F44D9CC615261759003D3E8F /* Supporting Files */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | F44D9CC715261759003D3E8F /* ViewPagerExample-Info.plist */, 108 | F44D9CC815261759003D3E8F /* InfoPlist.strings */, 109 | F44D9CCB15261759003D3E8F /* main.m */, 110 | F44D9CCD15261759003D3E8F /* ViewPagerExample-Prefix.pch */, 111 | ); 112 | name = "Supporting Files"; 113 | sourceTree = ""; 114 | }; 115 | /* End PBXGroup section */ 116 | 117 | /* Begin PBXNativeTarget section */ 118 | F44D9CBA15261759003D3E8F /* ViewPagerExample */ = { 119 | isa = PBXNativeTarget; 120 | buildConfigurationList = F44D9CD915261759003D3E8F /* Build configuration list for PBXNativeTarget "ViewPagerExample" */; 121 | buildPhases = ( 122 | F44D9CB715261759003D3E8F /* Sources */, 123 | F44D9CB815261759003D3E8F /* Frameworks */, 124 | F44D9CB915261759003D3E8F /* Resources */, 125 | ); 126 | buildRules = ( 127 | ); 128 | dependencies = ( 129 | ); 130 | name = ViewPagerExample; 131 | productName = ViewPager; 132 | productReference = F44D9CBB15261759003D3E8F /* ViewPagerExample.app */; 133 | productType = "com.apple.product-type.application"; 134 | }; 135 | /* End PBXNativeTarget section */ 136 | 137 | /* Begin PBXProject section */ 138 | F44D9CB215261759003D3E8F /* Project object */ = { 139 | isa = PBXProject; 140 | attributes = { 141 | CLASSPREFIX = SG; 142 | LastUpgradeCheck = 0430; 143 | }; 144 | buildConfigurationList = F44D9CB515261759003D3E8F /* Build configuration list for PBXProject "ViewPagerExample" */; 145 | compatibilityVersion = "Xcode 3.2"; 146 | developmentRegion = English; 147 | hasScannedForEncodings = 0; 148 | knownRegions = ( 149 | en, 150 | ); 151 | mainGroup = F44D9CB015261759003D3E8F; 152 | productRefGroup = F44D9CBC15261759003D3E8F /* Products */; 153 | projectDirPath = ""; 154 | projectRoot = ""; 155 | targets = ( 156 | F44D9CBA15261759003D3E8F /* ViewPagerExample */, 157 | ); 158 | }; 159 | /* End PBXProject section */ 160 | 161 | /* Begin PBXResourcesBuildPhase section */ 162 | F44D9CB915261759003D3E8F /* Resources */ = { 163 | isa = PBXResourcesBuildPhase; 164 | buildActionMask = 2147483647; 165 | files = ( 166 | F44D9CCA15261759003D3E8F /* InfoPlist.strings in Resources */, 167 | F44D9CD615261759003D3E8F /* SGViewPagerController.xib in Resources */, 168 | F40AE30C15297F1800F7C596 /* SGAnnotatedPagerController.xib in Resources */, 169 | ); 170 | runOnlyForDeploymentPostprocessing = 0; 171 | }; 172 | /* End PBXResourcesBuildPhase section */ 173 | 174 | /* Begin PBXSourcesBuildPhase section */ 175 | F44D9CB715261759003D3E8F /* Sources */ = { 176 | isa = PBXSourcesBuildPhase; 177 | buildActionMask = 2147483647; 178 | files = ( 179 | F44D9CCC15261759003D3E8F /* main.m in Sources */, 180 | F44D9CD015261759003D3E8F /* SGAppDelegate.m in Sources */, 181 | F44D9CD315261759003D3E8F /* SGExampleController.m in Sources */, 182 | F48B41A31529BEB100931141 /* SGAnnotatedPagerController.m in Sources */, 183 | F48B41A41529BEB100931141 /* SGViewPagerController.m in Sources */, 184 | ); 185 | runOnlyForDeploymentPostprocessing = 0; 186 | }; 187 | /* End PBXSourcesBuildPhase section */ 188 | 189 | /* Begin PBXVariantGroup section */ 190 | F40AE30A15297F1800F7C596 /* SGAnnotatedPagerController.xib */ = { 191 | isa = PBXVariantGroup; 192 | children = ( 193 | F40AE30B15297F1800F7C596 /* en */, 194 | ); 195 | name = SGAnnotatedPagerController.xib; 196 | sourceTree = ""; 197 | }; 198 | F44D9CC815261759003D3E8F /* InfoPlist.strings */ = { 199 | isa = PBXVariantGroup; 200 | children = ( 201 | F44D9CC915261759003D3E8F /* en */, 202 | ); 203 | name = InfoPlist.strings; 204 | sourceTree = ""; 205 | }; 206 | F44D9CD415261759003D3E8F /* SGViewPagerController.xib */ = { 207 | isa = PBXVariantGroup; 208 | children = ( 209 | F44D9CD515261759003D3E8F /* en */, 210 | ); 211 | name = SGViewPagerController.xib; 212 | sourceTree = ""; 213 | }; 214 | /* End PBXVariantGroup section */ 215 | 216 | /* Begin XCBuildConfiguration section */ 217 | F44D9CD715261759003D3E8F /* Debug */ = { 218 | isa = XCBuildConfiguration; 219 | buildSettings = { 220 | ALWAYS_SEARCH_USER_PATHS = NO; 221 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 222 | CLANG_ENABLE_OBJC_ARC = YES; 223 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 224 | COPY_PHASE_STRIP = NO; 225 | GCC_C_LANGUAGE_STANDARD = gnu99; 226 | GCC_DYNAMIC_NO_PIC = NO; 227 | GCC_OPTIMIZATION_LEVEL = 0; 228 | GCC_PREPROCESSOR_DEFINITIONS = ( 229 | "DEBUG=1", 230 | "$(inherited)", 231 | ); 232 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 233 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 234 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 235 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 236 | GCC_WARN_UNUSED_VARIABLE = YES; 237 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 238 | SDKROOT = iphoneos; 239 | }; 240 | name = Debug; 241 | }; 242 | F44D9CD815261759003D3E8F /* Release */ = { 243 | isa = XCBuildConfiguration; 244 | buildSettings = { 245 | ALWAYS_SEARCH_USER_PATHS = NO; 246 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 247 | CLANG_ENABLE_OBJC_ARC = YES; 248 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 249 | COPY_PHASE_STRIP = YES; 250 | GCC_C_LANGUAGE_STANDARD = gnu99; 251 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 252 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 253 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 254 | GCC_WARN_UNUSED_VARIABLE = YES; 255 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 256 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 257 | SDKROOT = iphoneos; 258 | VALIDATE_PRODUCT = YES; 259 | }; 260 | name = Release; 261 | }; 262 | F44D9CDA15261759003D3E8F /* Debug */ = { 263 | isa = XCBuildConfiguration; 264 | buildSettings = { 265 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 266 | GCC_PREFIX_HEADER = "ViewPager/ViewPagerExample-Prefix.pch"; 267 | INFOPLIST_FILE = "ViewPager/ViewPagerExample-Info.plist"; 268 | PRODUCT_NAME = ViewPagerExample; 269 | WRAPPER_EXTENSION = app; 270 | }; 271 | name = Debug; 272 | }; 273 | F44D9CDB15261759003D3E8F /* Release */ = { 274 | isa = XCBuildConfiguration; 275 | buildSettings = { 276 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 277 | GCC_PREFIX_HEADER = "ViewPager/ViewPagerExample-Prefix.pch"; 278 | INFOPLIST_FILE = "ViewPager/ViewPagerExample-Info.plist"; 279 | PRODUCT_NAME = ViewPagerExample; 280 | WRAPPER_EXTENSION = app; 281 | }; 282 | name = Release; 283 | }; 284 | /* End XCBuildConfiguration section */ 285 | 286 | /* Begin XCConfigurationList section */ 287 | F44D9CB515261759003D3E8F /* Build configuration list for PBXProject "ViewPagerExample" */ = { 288 | isa = XCConfigurationList; 289 | buildConfigurations = ( 290 | F44D9CD715261759003D3E8F /* Debug */, 291 | F44D9CD815261759003D3E8F /* Release */, 292 | ); 293 | defaultConfigurationIsVisible = 0; 294 | defaultConfigurationName = Release; 295 | }; 296 | F44D9CD915261759003D3E8F /* Build configuration list for PBXNativeTarget "ViewPagerExample" */ = { 297 | isa = XCConfigurationList; 298 | buildConfigurations = ( 299 | F44D9CDA15261759003D3E8F /* Debug */, 300 | F44D9CDB15261759003D3E8F /* Release */, 301 | ); 302 | defaultConfigurationIsVisible = 0; 303 | defaultConfigurationName = Release; 304 | }; 305 | /* End XCConfigurationList section */ 306 | }; 307 | rootObject = F44D9CB215261759003D3E8F /* Project object */; 308 | } 309 | --------------------------------------------------------------------------------