├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── Example ├── Classes │ ├── App Delegate │ │ ├── RDVAppDelegate.h │ │ └── RDVAppDelegate.m │ └── Controllers │ │ ├── RDVDetailsViewController.h │ │ ├── RDVDetailsViewController.m │ │ ├── RDVFirstViewController.h │ │ ├── RDVFirstViewController.m │ │ ├── RDVSecondViewController.h │ │ ├── RDVSecondViewController.m │ │ ├── RDVThirdViewController.h │ │ └── RDVThirdViewController.m ├── Default-568h@2x.png ├── Default.png ├── Default@2x.png ├── Images │ ├── first_normal.png │ ├── first_normal@2x.png │ ├── first_selected.png │ ├── first_selected@2x.png │ ├── navigationbar_background.png │ ├── navigationbar_background@2x.png │ ├── navigationbar_background_tall.png │ ├── navigationbar_background_tall@2x.png │ ├── second_normal.png │ ├── second_normal@2x.png │ ├── second_selected.png │ ├── second_selected@2x.png │ ├── tabbar_normal_background.png │ ├── tabbar_normal_background@2x.png │ ├── tabbar_selected_background.png │ ├── tabbar_selected_background@2x.png │ ├── third_normal.png │ ├── third_normal@2x.png │ ├── third_selected.png │ └── third_selected@2x.png ├── LaunchScreen.storyboard ├── RDVTabBarController-Info.plist ├── RDVTabBarController-Prefix.pch ├── en.lproj │ └── InfoPlist.strings └── main.m ├── LICENSE ├── RDVTabBarController.podspec ├── RDVTabBarController.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── RDVTabBarController ├── RDVTabBar.h ├── RDVTabBar.m ├── RDVTabBarController.h ├── RDVTabBarController.m ├── RDVTabBarItem.h └── RDVTabBarItem.m ├── README.md └── Screenshots ├── iPad-small.png ├── iPad.png ├── iPhone-small.png └── iPhone.png /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Description 2 | 3 | [Description of the issue] 4 | 5 | ### Steps to Reproduce 6 | 7 | [Steps or usage snippet reproducing the issue] 8 | 9 | 1. [First Step] 10 | 2. [Second Step] 11 | 3. [and so on...] 12 | 13 | ``` 14 | 15 | ``` 16 | 17 | **Expected behavior:** [What you expect to happen] 18 | **Actual behavior:** [What actually happens] 19 | **Reproduces how often:** [What percentage of the time does it reproduce?] 20 | 21 | ### System configuration 22 | 23 | Xcode version: 24 | iOS version: 25 | Affected device: 26 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Summary 2 | 3 | 7 | 8 | ### Other Information 9 | 10 | 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 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 | xcshareddata 14 | profile 15 | *.moved-aside 16 | DerivedData 17 | .idea/ 18 | *.hmap 19 | -------------------------------------------------------------------------------- /Example/Classes/App Delegate/RDVAppDelegate.h: -------------------------------------------------------------------------------- 1 | // RDVAppDelegate.h 2 | // RDVTabBarController 3 | // 4 | // Copyright (c) 2013 Robert Dimitrov 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #import 25 | 26 | @interface RDVAppDelegate : UIResponder 27 | 28 | @property (strong, nonatomic) UIWindow *window; 29 | @property (strong, nonatomic) UIViewController *viewController; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /Example/Classes/App Delegate/RDVAppDelegate.m: -------------------------------------------------------------------------------- 1 | // RDVAppDelegate.m 2 | // RDVTabBarController 3 | // 4 | // Copyright (c) 2013 Robert Dimitrov 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #import "RDVAppDelegate.h" 25 | #import "RDVFirstViewController.h" 26 | #import "RDVSecondViewController.h" 27 | #import "RDVThirdViewController.h" 28 | #import "RDVTabBarController.h" 29 | #import "RDVTabBarItem.h" 30 | 31 | @implementation RDVAppDelegate 32 | 33 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 34 | { 35 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 36 | self.window.backgroundColor = [UIColor whiteColor]; 37 | [self setupViewControllers]; 38 | [self.window setRootViewController:self.viewController]; 39 | [self.window makeKeyAndVisible]; 40 | 41 | [self customizeInterface]; 42 | 43 | return YES; 44 | } 45 | 46 | #pragma mark - Methods 47 | 48 | - (void)setupViewControllers { 49 | UIViewController *firstViewController = [[RDVFirstViewController alloc] init]; 50 | UIViewController *firstNavigationController = [[UINavigationController alloc] 51 | initWithRootViewController:firstViewController]; 52 | 53 | UIViewController *secondViewController = [[RDVSecondViewController alloc] init]; 54 | UIViewController *secondNavigationController = [[UINavigationController alloc] 55 | initWithRootViewController:secondViewController]; 56 | 57 | UIViewController *thirdViewController = [[RDVThirdViewController alloc] init]; 58 | UIViewController *thirdNavigationController = [[UINavigationController alloc] 59 | initWithRootViewController:thirdViewController]; 60 | 61 | RDVTabBarController *tabBarController = [[RDVTabBarController alloc] init]; 62 | [tabBarController setViewControllers:@[firstNavigationController, secondNavigationController, 63 | thirdNavigationController]]; 64 | self.viewController = tabBarController; 65 | 66 | [self customizeTabBarForController:tabBarController]; 67 | } 68 | 69 | - (void)customizeTabBarForController:(RDVTabBarController *)tabBarController { 70 | UIImage *finishedImage = [UIImage imageNamed:@"tabbar_selected_background"]; 71 | UIImage *unfinishedImage = [UIImage imageNamed:@"tabbar_normal_background"]; 72 | NSArray *tabBarItemImages = @[@"first", @"second", @"third"]; 73 | 74 | NSInteger index = 0; 75 | for (RDVTabBarItem *item in [[tabBarController tabBar] items]) { 76 | [item setBackgroundSelectedImage:finishedImage withUnselectedImage:unfinishedImage]; 77 | UIImage *selectedimage = [UIImage imageNamed:[NSString stringWithFormat:@"%@_selected", 78 | [tabBarItemImages objectAtIndex:index]]]; 79 | UIImage *unselectedimage = [UIImage imageNamed:[NSString stringWithFormat:@"%@_normal", 80 | [tabBarItemImages objectAtIndex:index]]]; 81 | [item setFinishedSelectedImage:selectedimage withFinishedUnselectedImage:unselectedimage]; 82 | 83 | index++; 84 | } 85 | } 86 | 87 | - (void)customizeInterface { 88 | UINavigationBar *navigationBarAppearance = [UINavigationBar appearance]; 89 | 90 | UIImage *backgroundImage = nil; 91 | NSDictionary *textAttributes = nil; 92 | 93 | if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) { 94 | backgroundImage = [UIImage imageNamed:@"navigationbar_background_tall"]; 95 | 96 | textAttributes = @{ 97 | NSFontAttributeName: [UIFont boldSystemFontOfSize:18], 98 | NSForegroundColorAttributeName: [UIColor blackColor], 99 | }; 100 | } else { 101 | #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_7_0 102 | backgroundImage = [UIImage imageNamed:@"navigationbar_background"]; 103 | 104 | textAttributes = @{ 105 | UITextAttributeFont: [UIFont boldSystemFontOfSize:18], 106 | UITextAttributeTextColor: [UIColor blackColor], 107 | UITextAttributeTextShadowColor: [UIColor clearColor], 108 | UITextAttributeTextShadowOffset: [NSValue valueWithUIOffset:UIOffsetZero], 109 | }; 110 | #endif 111 | } 112 | 113 | [navigationBarAppearance setBackgroundImage:backgroundImage 114 | forBarMetrics:UIBarMetricsDefault]; 115 | [navigationBarAppearance setTitleTextAttributes:textAttributes]; 116 | } 117 | 118 | @end 119 | -------------------------------------------------------------------------------- /Example/Classes/Controllers/RDVDetailsViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RDVDetailsViewController.h 3 | // RDVTabBarController 4 | // 5 | // Created by Robert Dimitrov on 11/8/14. 6 | // Copyright (c) 2014 Robert Dimitrov. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RDVDetailsViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Example/Classes/Controllers/RDVDetailsViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RDVDetailsViewController.m 3 | // RDVTabBarController 4 | // 5 | // Created by Robert Dimitrov on 11/8/14. 6 | // Copyright (c) 2014 Robert Dimitrov. All rights reserved. 7 | // 8 | 9 | #import "RDVDetailsViewController.h" 10 | #import "RDVTabBarController.h" 11 | 12 | @interface RDVDetailsViewController () 13 | 14 | @end 15 | 16 | @implementation RDVDetailsViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | 21 | self.title = NSLocalizedString(@"Details", nil); 22 | self.view.backgroundColor = [UIColor colorWithRed:250/255.0 green:250/255.0 blue:250/255.0 alpha:1.0]; 23 | 24 | UILabel *label = [[UILabel alloc] init]; 25 | label.text = NSLocalizedString(@"Detail View Controller", nil); 26 | label.frame = CGRectMake(20, 150, CGRectGetWidth(self.view.frame) - 2 * 20, 20); 27 | label.autoresizingMask = UIViewAutoresizingFlexibleWidth; 28 | label.textAlignment = NSTextAlignmentCenter; 29 | [self.view addSubview:label]; 30 | } 31 | 32 | - (void)viewWillAppear:(BOOL)animated { 33 | [super viewWillAppear:animated]; 34 | 35 | [[self rdv_tabBarController] setTabBarHidden:YES animated:YES]; 36 | } 37 | 38 | - (void)viewWillDisappear:(BOOL)animated { 39 | [[self rdv_tabBarController] setTabBarHidden:NO animated:YES]; 40 | 41 | [super viewWillDisappear:animated]; 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /Example/Classes/Controllers/RDVFirstViewController.h: -------------------------------------------------------------------------------- 1 | // RDVFirstViewController.h 2 | // RDVTabBarController 3 | // 4 | // Copyright (c) 2013 Robert Dimitrov 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #import 25 | 26 | @interface RDVFirstViewController : UITableViewController 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Example/Classes/Controllers/RDVFirstViewController.m: -------------------------------------------------------------------------------- 1 | // RDVFirstViewController.m 2 | // RDVTabBarController 3 | // 4 | // Copyright (c) 2013 Robert Dimitrov 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #import "RDVFirstViewController.h" 25 | #import "RDVTabBarController.h" 26 | #import "RDVTabBarItem.h" 27 | 28 | @implementation RDVFirstViewController 29 | 30 | - (instancetype)init { 31 | self = [super init]; 32 | if (self) { 33 | self.title = NSLocalizedString(@"First", nil); 34 | } 35 | return self; 36 | } 37 | 38 | #pragma mark - View lifecycle 39 | 40 | - (void)viewDidLoad { 41 | [super viewDidLoad]; 42 | 43 | [[self rdv_tabBarItem] setBadgeValue:@"3"]; 44 | 45 | if (self.rdv_tabBarController.tabBar.translucent) { 46 | UIEdgeInsets insets = UIEdgeInsetsMake(0, 47 | 0, 48 | CGRectGetHeight(self.rdv_tabBarController.tabBar.frame), 49 | 0); 50 | 51 | self.tableView.contentInset = insets; 52 | self.tableView.scrollIndicatorInsets = insets; 53 | } 54 | } 55 | 56 | #pragma mark - Methods 57 | 58 | - (void)configureCell:(UITableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath { 59 | [[cell textLabel] setText:[NSString stringWithFormat:@"%@ Controller Cell %ld", self.title, (long)indexPath.row]]; 60 | } 61 | 62 | #pragma mark - Table view 63 | 64 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 65 | static NSString *CellIdentifier = @"Cell"; 66 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 67 | if (!cell) { 68 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 69 | } 70 | 71 | [self configureCell:cell forIndexPath:indexPath]; 72 | 73 | return cell; 74 | } 75 | 76 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 77 | return 30; 78 | } 79 | 80 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 81 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 82 | 83 | [[self rdv_tabBarItem] setBadgeValue:[NSString stringWithFormat:@"%ld", indexPath.row+1]]; 84 | } 85 | 86 | @end 87 | -------------------------------------------------------------------------------- /Example/Classes/Controllers/RDVSecondViewController.h: -------------------------------------------------------------------------------- 1 | // RDVSecondViewController.h 2 | // RDVTabBarController 3 | // 4 | // Copyright (c) 2013 Robert Dimitrov 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #import 25 | 26 | @interface RDVSecondViewController : UITableViewController 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Example/Classes/Controllers/RDVSecondViewController.m: -------------------------------------------------------------------------------- 1 | // RDVSecondViewController.m 2 | // RDVTabBarController 3 | // 4 | // Copyright (c) 2013 Robert Dimitrov 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #import "RDVSecondViewController.h" 25 | #import "RDVTabBarController.h" 26 | 27 | @implementation RDVSecondViewController 28 | 29 | - (instancetype)init { 30 | self = [super init]; 31 | if (self) { 32 | self.title = NSLocalizedString(@"Second", nil); 33 | } 34 | return self; 35 | } 36 | 37 | #pragma mark - View lifecycle 38 | 39 | - (void)viewDidLoad { 40 | [super viewDidLoad]; 41 | 42 | if (self.rdv_tabBarController.tabBar.translucent) { 43 | UIEdgeInsets insets = UIEdgeInsetsMake(0, 44 | 0, 45 | CGRectGetHeight(self.rdv_tabBarController.tabBar.frame), 46 | 0); 47 | 48 | self.tableView.contentInset = insets; 49 | self.tableView.scrollIndicatorInsets = insets; 50 | } 51 | } 52 | 53 | #pragma mark - Methods 54 | 55 | - (void)configureCell:(UITableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath { 56 | [[cell textLabel] setText:[NSString stringWithFormat:@"%@ Controller Cell %ld", self.title, (long)indexPath.row]]; 57 | } 58 | 59 | #pragma mark - Table view 60 | 61 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 62 | static NSString *CellIdentifier = @"Cell"; 63 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 64 | if (!cell) { 65 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 66 | } 67 | 68 | [self configureCell:cell forIndexPath:indexPath]; 69 | 70 | return cell; 71 | } 72 | 73 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 74 | return 15; 75 | } 76 | 77 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 78 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 79 | 80 | [[self rdv_tabBarController] setTabBarHidden:!self.rdv_tabBarController.tabBarHidden animated:YES]; 81 | } 82 | 83 | @end 84 | -------------------------------------------------------------------------------- /Example/Classes/Controllers/RDVThirdViewController.h: -------------------------------------------------------------------------------- 1 | // RDVThirdViewController.h 2 | // RDVTabBarController 3 | // 4 | // Copyright (c) 2013 Robert Dimitrov 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #import 25 | 26 | @interface RDVThirdViewController : UITableViewController 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Example/Classes/Controllers/RDVThirdViewController.m: -------------------------------------------------------------------------------- 1 | // RDVThirdViewController.m 2 | // RDVTabBarController 3 | // 4 | // Copyright (c) 2013 Robert Dimitrov 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #import "RDVThirdViewController.h" 25 | #import "RDVTabBarController.h" 26 | #import "RDVDetailsViewController.h" 27 | 28 | @implementation RDVThirdViewController 29 | 30 | - (instancetype)init { 31 | self = [super init]; 32 | if (self) { 33 | self.title = NSLocalizedString(@"Third", nil); 34 | } 35 | return self; 36 | } 37 | 38 | #pragma mark - View lifecycle 39 | 40 | - (void)viewDidLoad { 41 | [super viewDidLoad]; 42 | 43 | if (self.rdv_tabBarController.tabBar.translucent) { 44 | UIEdgeInsets insets = UIEdgeInsetsMake(0, 45 | 0, 46 | CGRectGetHeight(self.rdv_tabBarController.tabBar.frame), 47 | 0); 48 | 49 | self.tableView.contentInset = insets; 50 | self.tableView.scrollIndicatorInsets = insets; 51 | } 52 | } 53 | 54 | #pragma mark - Methods 55 | 56 | - (void)configureCell:(UITableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath { 57 | [[cell textLabel] setText:[NSString stringWithFormat:@"%@ Controller Cell %ld", self.title, (long)indexPath.row]]; 58 | } 59 | 60 | #pragma mark - Table view 61 | 62 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 63 | static NSString *CellIdentifier = @"Cell"; 64 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 65 | if (!cell) { 66 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 67 | } 68 | 69 | [self configureCell:cell forIndexPath:indexPath]; 70 | 71 | return cell; 72 | } 73 | 74 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 75 | return 15; 76 | } 77 | 78 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 79 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 80 | 81 | UIViewController *viewController = [[RDVDetailsViewController alloc] init]; 82 | [self.navigationController pushViewController:viewController animated:YES]; 83 | } 84 | 85 | @end 86 | -------------------------------------------------------------------------------- /Example/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Example/Default-568h@2x.png -------------------------------------------------------------------------------- /Example/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Example/Default.png -------------------------------------------------------------------------------- /Example/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Example/Default@2x.png -------------------------------------------------------------------------------- /Example/Images/first_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Example/Images/first_normal.png -------------------------------------------------------------------------------- /Example/Images/first_normal@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Example/Images/first_normal@2x.png -------------------------------------------------------------------------------- /Example/Images/first_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Example/Images/first_selected.png -------------------------------------------------------------------------------- /Example/Images/first_selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Example/Images/first_selected@2x.png -------------------------------------------------------------------------------- /Example/Images/navigationbar_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Example/Images/navigationbar_background.png -------------------------------------------------------------------------------- /Example/Images/navigationbar_background@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Example/Images/navigationbar_background@2x.png -------------------------------------------------------------------------------- /Example/Images/navigationbar_background_tall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Example/Images/navigationbar_background_tall.png -------------------------------------------------------------------------------- /Example/Images/navigationbar_background_tall@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Example/Images/navigationbar_background_tall@2x.png -------------------------------------------------------------------------------- /Example/Images/second_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Example/Images/second_normal.png -------------------------------------------------------------------------------- /Example/Images/second_normal@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Example/Images/second_normal@2x.png -------------------------------------------------------------------------------- /Example/Images/second_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Example/Images/second_selected.png -------------------------------------------------------------------------------- /Example/Images/second_selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Example/Images/second_selected@2x.png -------------------------------------------------------------------------------- /Example/Images/tabbar_normal_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Example/Images/tabbar_normal_background.png -------------------------------------------------------------------------------- /Example/Images/tabbar_normal_background@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Example/Images/tabbar_normal_background@2x.png -------------------------------------------------------------------------------- /Example/Images/tabbar_selected_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Example/Images/tabbar_selected_background.png -------------------------------------------------------------------------------- /Example/Images/tabbar_selected_background@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Example/Images/tabbar_selected_background@2x.png -------------------------------------------------------------------------------- /Example/Images/third_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Example/Images/third_normal.png -------------------------------------------------------------------------------- /Example/Images/third_normal@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Example/Images/third_normal@2x.png -------------------------------------------------------------------------------- /Example/Images/third_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Example/Images/third_selected.png -------------------------------------------------------------------------------- /Example/Images/third_selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Example/Images/third_selected@2x.png -------------------------------------------------------------------------------- /Example/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Example/RDVTabBarController-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 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 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Example/RDVTabBarController-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'RDVTabBarController' target in the 'RDVTabBarController' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_3_0 8 | #warning "This project uses features only available in iOS SDK 3.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /Example/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/main.m: -------------------------------------------------------------------------------- 1 | // main.m 2 | // RDVTabBarController 3 | // 4 | // Copyright (c) 2013 Robert Dimitrov 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #import 25 | 26 | #import "RDVAppDelegate.h" 27 | 28 | int main(int argc, char *argv[]) 29 | { 30 | @autoreleasepool { 31 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([RDVAppDelegate class])); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013-2014 Robert Dimitrov 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 4 | associated documentation files (the "Software"), to deal in the Software without restriction, 5 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 6 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 7 | subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or 10 | substantial portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 13 | LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 14 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 16 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | -------------------------------------------------------------------------------- /RDVTabBarController.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "RDVTabBarController" 3 | s.version = "1.3.0" 4 | s.summary = "Highly customizable tabBar and tabBarController for iOS" 5 | s.description = "RDVTabBarController is iPad and iPhone compatible. Supports landscape and portrait orientations and can be used inside UINavigationController." 6 | s.homepage = "https://github.com/robbdimitrov/RDVTabBarController" 7 | s.license = { :type => 'MIT', :file => 'LICENSE' } 8 | s.author = { "Robert Dimitrov" => "robert_dimitrov@me.com" } 9 | s.platform = :ios, '8.0' 10 | s.source = { :git => "https://github.com/robbdimitrov/RDVTabBarController.git", :tag => "v1.3.0" } 11 | s.source_files = 'RDVTabBarController', 'RDVTabBarController/**/*.{h,m}' 12 | s.framework = 'UIKit', 'CoreGraphics', 'Foundation' 13 | s.requires_arc = true 14 | end 15 | -------------------------------------------------------------------------------- /RDVTabBarController.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | B407B65B182CCA01006F21A6 /* navigationbar_background.png in Resources */ = {isa = PBXBuildFile; fileRef = B407B659182CCA01006F21A6 /* navigationbar_background.png */; }; 11 | B407B65C182CCA01006F21A6 /* navigationbar_background@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B407B65A182CCA01006F21A6 /* navigationbar_background@2x.png */; }; 12 | B435F4F917396A8D00297C82 /* RDVTabBarItem.m in Sources */ = {isa = PBXBuildFile; fileRef = B435F4F817396A8D00297C82 /* RDVTabBarItem.m */; }; 13 | B44008E2180B11A500D8CB89 /* tabbar_normal_background.png in Resources */ = {isa = PBXBuildFile; fileRef = B44008D4180B11A500D8CB89 /* tabbar_normal_background.png */; }; 14 | B44008E3180B11A500D8CB89 /* tabbar_normal_background@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B44008D5180B11A500D8CB89 /* tabbar_normal_background@2x.png */; }; 15 | B44008E4180B11A500D8CB89 /* tabbar_selected_background.png in Resources */ = {isa = PBXBuildFile; fileRef = B44008D6180B11A500D8CB89 /* tabbar_selected_background.png */; }; 16 | B44008E5180B11A500D8CB89 /* tabbar_selected_background@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B44008D7180B11A500D8CB89 /* tabbar_selected_background@2x.png */; }; 17 | B44008E6180B11A500D8CB89 /* first_normal.png in Resources */ = {isa = PBXBuildFile; fileRef = B44008D8180B11A500D8CB89 /* first_normal.png */; }; 18 | B44008E7180B11A500D8CB89 /* first_normal@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B44008D9180B11A500D8CB89 /* first_normal@2x.png */; }; 19 | B44008E8180B11A500D8CB89 /* first_selected.png in Resources */ = {isa = PBXBuildFile; fileRef = B44008DA180B11A500D8CB89 /* first_selected.png */; }; 20 | B44008E9180B11A500D8CB89 /* first_selected@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B44008DB180B11A500D8CB89 /* first_selected@2x.png */; }; 21 | B44008EA180B11A500D8CB89 /* navigationbar_background_tall.png in Resources */ = {isa = PBXBuildFile; fileRef = B44008DC180B11A500D8CB89 /* navigationbar_background_tall.png */; }; 22 | B44008EB180B11A500D8CB89 /* navigationbar_background_tall@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B44008DD180B11A500D8CB89 /* navigationbar_background_tall@2x.png */; }; 23 | B44008EC180B11A500D8CB89 /* second_normal.png in Resources */ = {isa = PBXBuildFile; fileRef = B44008DE180B11A500D8CB89 /* second_normal.png */; }; 24 | B44008ED180B11A500D8CB89 /* second_normal@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B44008DF180B11A500D8CB89 /* second_normal@2x.png */; }; 25 | B44008EE180B11A500D8CB89 /* second_selected.png in Resources */ = {isa = PBXBuildFile; fileRef = B44008E0180B11A500D8CB89 /* second_selected.png */; }; 26 | B44008EF180B11A500D8CB89 /* second_selected@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B44008E1180B11A500D8CB89 /* second_selected@2x.png */; }; 27 | B44008F4180B185E00D8CB89 /* third_normal.png in Resources */ = {isa = PBXBuildFile; fileRef = B44008F0180B185E00D8CB89 /* third_normal.png */; }; 28 | B44008F5180B185E00D8CB89 /* third_normal@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B44008F1180B185E00D8CB89 /* third_normal@2x.png */; }; 29 | B44008F6180B185E00D8CB89 /* third_selected.png in Resources */ = {isa = PBXBuildFile; fileRef = B44008F2180B185E00D8CB89 /* third_selected.png */; }; 30 | B44008F7180B185E00D8CB89 /* third_selected@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B44008F3180B185E00D8CB89 /* third_selected@2x.png */; }; 31 | B453D33A1A0E2219002F5656 /* RDVDetailsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B453D3391A0E2219002F5656 /* RDVDetailsViewController.m */; }; 32 | B4616BAF17228DF700863892 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B4616BAE17228DF700863892 /* UIKit.framework */; }; 33 | B4616BB117228DF700863892 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B4616BB017228DF700863892 /* Foundation.framework */; }; 34 | B4616BB317228DF700863892 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B4616BB217228DF700863892 /* CoreGraphics.framework */; }; 35 | B4616C00172298FE00863892 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B4616BF5172298FE00863892 /* Default-568h@2x.png */; }; 36 | B4616C01172298FE00863892 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = B4616BF6172298FE00863892 /* Default.png */; }; 37 | B4616C02172298FE00863892 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B4616BF7172298FE00863892 /* Default@2x.png */; }; 38 | B4616C03172298FE00863892 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = B4616BF9172298FE00863892 /* InfoPlist.strings */; }; 39 | B4616C04172298FE00863892 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B4616BFB172298FE00863892 /* main.m */; }; 40 | B4616C0C1722995D00863892 /* RDVAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = B4616C0A1722995D00863892 /* RDVAppDelegate.m */; }; 41 | B465733A1725A23D00319236 /* RDVFirstViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B46573391725A23D00319236 /* RDVFirstViewController.m */; }; 42 | B465733D1725A24700319236 /* RDVSecondViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B465733C1725A24700319236 /* RDVSecondViewController.m */; }; 43 | B46573401725A25100319236 /* RDVThirdViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B465733F1725A25100319236 /* RDVThirdViewController.m */; }; 44 | B49817A617229BB500AD294C /* RDVTabBar.m in Sources */ = {isa = PBXBuildFile; fileRef = B49817A517229BB500AD294C /* RDVTabBar.m */; }; 45 | B49817A917229CBC00AD294C /* RDVTabBarController.m in Sources */ = {isa = PBXBuildFile; fileRef = B49817A817229CBC00AD294C /* RDVTabBarController.m */; }; 46 | B4A37571217CADCC0008264D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B4A37570217CADCC0008264D /* LaunchScreen.storyboard */; }; 47 | B4A63267176F6145004644CA /* iPad.png in Resources */ = {isa = PBXBuildFile; fileRef = B4A63265176F6145004644CA /* iPad.png */; }; 48 | B4A63268176F6145004644CA /* iPhone.png in Resources */ = {isa = PBXBuildFile; fileRef = B4A63266176F6145004644CA /* iPhone.png */; }; 49 | B4A742CD176E1BF10055367E /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = B4A742CB176E1BF10055367E /* LICENSE */; }; 50 | B4A742CE176E1BF10055367E /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = B4A742CC176E1BF10055367E /* README.md */; }; 51 | B4DB36A1182C4B7C0008898E /* iPad-small.png in Resources */ = {isa = PBXBuildFile; fileRef = B4DB369F182C4B7C0008898E /* iPad-small.png */; }; 52 | B4DB36A2182C4B7C0008898E /* iPhone-small.png in Resources */ = {isa = PBXBuildFile; fileRef = B4DB36A0182C4B7C0008898E /* iPhone-small.png */; }; 53 | /* End PBXBuildFile section */ 54 | 55 | /* Begin PBXFileReference section */ 56 | B407B659182CCA01006F21A6 /* navigationbar_background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = navigationbar_background.png; sourceTree = ""; }; 57 | B407B65A182CCA01006F21A6 /* navigationbar_background@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "navigationbar_background@2x.png"; sourceTree = ""; }; 58 | B435F4F717396A8D00297C82 /* RDVTabBarItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RDVTabBarItem.h; sourceTree = ""; }; 59 | B435F4F817396A8D00297C82 /* RDVTabBarItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RDVTabBarItem.m; sourceTree = ""; }; 60 | B44008D4180B11A500D8CB89 /* tabbar_normal_background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tabbar_normal_background.png; sourceTree = ""; }; 61 | B44008D5180B11A500D8CB89 /* tabbar_normal_background@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "tabbar_normal_background@2x.png"; sourceTree = ""; }; 62 | B44008D6180B11A500D8CB89 /* tabbar_selected_background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tabbar_selected_background.png; sourceTree = ""; }; 63 | B44008D7180B11A500D8CB89 /* tabbar_selected_background@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "tabbar_selected_background@2x.png"; sourceTree = ""; }; 64 | B44008D8180B11A500D8CB89 /* first_normal.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = first_normal.png; sourceTree = ""; }; 65 | B44008D9180B11A500D8CB89 /* first_normal@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "first_normal@2x.png"; sourceTree = ""; }; 66 | B44008DA180B11A500D8CB89 /* first_selected.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = first_selected.png; sourceTree = ""; }; 67 | B44008DB180B11A500D8CB89 /* first_selected@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "first_selected@2x.png"; sourceTree = ""; }; 68 | B44008DC180B11A500D8CB89 /* navigationbar_background_tall.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = navigationbar_background_tall.png; sourceTree = ""; }; 69 | B44008DD180B11A500D8CB89 /* navigationbar_background_tall@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "navigationbar_background_tall@2x.png"; sourceTree = ""; }; 70 | B44008DE180B11A500D8CB89 /* second_normal.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = second_normal.png; sourceTree = ""; }; 71 | B44008DF180B11A500D8CB89 /* second_normal@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "second_normal@2x.png"; sourceTree = ""; }; 72 | B44008E0180B11A500D8CB89 /* second_selected.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = second_selected.png; sourceTree = ""; }; 73 | B44008E1180B11A500D8CB89 /* second_selected@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "second_selected@2x.png"; sourceTree = ""; }; 74 | B44008F0180B185E00D8CB89 /* third_normal.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = third_normal.png; sourceTree = ""; }; 75 | B44008F1180B185E00D8CB89 /* third_normal@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "third_normal@2x.png"; sourceTree = ""; }; 76 | B44008F2180B185E00D8CB89 /* third_selected.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = third_selected.png; sourceTree = ""; }; 77 | B44008F3180B185E00D8CB89 /* third_selected@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "third_selected@2x.png"; sourceTree = ""; }; 78 | B453D3381A0E2219002F5656 /* RDVDetailsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RDVDetailsViewController.h; sourceTree = ""; }; 79 | B453D3391A0E2219002F5656 /* RDVDetailsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RDVDetailsViewController.m; sourceTree = ""; }; 80 | B4616BAB17228DF700863892 /* RDVTabBarController.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RDVTabBarController.app; sourceTree = BUILT_PRODUCTS_DIR; }; 81 | B4616BAE17228DF700863892 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 82 | B4616BB017228DF700863892 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 83 | B4616BB217228DF700863892 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 84 | B4616BF5172298FE00863892 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 85 | B4616BF6172298FE00863892 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; 86 | B4616BF7172298FE00863892 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; 87 | B4616BFA172298FE00863892 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = InfoPlist.strings; sourceTree = ""; }; 88 | B4616BFB172298FE00863892 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 89 | B4616BFE172298FE00863892 /* RDVTabBarController-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "RDVTabBarController-Info.plist"; sourceTree = ""; }; 90 | B4616BFF172298FE00863892 /* RDVTabBarController-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RDVTabBarController-Prefix.pch"; sourceTree = ""; }; 91 | B4616C091722995D00863892 /* RDVAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RDVAppDelegate.h; sourceTree = ""; }; 92 | B4616C0A1722995D00863892 /* RDVAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RDVAppDelegate.m; sourceTree = ""; }; 93 | B46573381725A23D00319236 /* RDVFirstViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RDVFirstViewController.h; sourceTree = ""; }; 94 | B46573391725A23D00319236 /* RDVFirstViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RDVFirstViewController.m; sourceTree = ""; }; 95 | B465733B1725A24700319236 /* RDVSecondViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RDVSecondViewController.h; sourceTree = ""; }; 96 | B465733C1725A24700319236 /* RDVSecondViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RDVSecondViewController.m; sourceTree = ""; }; 97 | B465733E1725A25100319236 /* RDVThirdViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RDVThirdViewController.h; sourceTree = ""; }; 98 | B465733F1725A25100319236 /* RDVThirdViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RDVThirdViewController.m; sourceTree = ""; }; 99 | B49817A417229BB500AD294C /* RDVTabBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RDVTabBar.h; sourceTree = ""; }; 100 | B49817A517229BB500AD294C /* RDVTabBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RDVTabBar.m; sourceTree = ""; }; 101 | B49817A717229CBC00AD294C /* RDVTabBarController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RDVTabBarController.h; sourceTree = ""; }; 102 | B49817A817229CBC00AD294C /* RDVTabBarController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RDVTabBarController.m; sourceTree = ""; }; 103 | B4A37570217CADCC0008264D /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; 104 | B4A63265176F6145004644CA /* iPad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = iPad.png; sourceTree = ""; }; 105 | B4A63266176F6145004644CA /* iPhone.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = iPhone.png; sourceTree = ""; }; 106 | B4A742CB176E1BF10055367E /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; 107 | B4A742CC176E1BF10055367E /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.md; sourceTree = ""; }; 108 | B4DB369F182C4B7C0008898E /* iPad-small.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iPad-small.png"; sourceTree = ""; }; 109 | B4DB36A0182C4B7C0008898E /* iPhone-small.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "iPhone-small.png"; sourceTree = ""; }; 110 | /* End PBXFileReference section */ 111 | 112 | /* Begin PBXFrameworksBuildPhase section */ 113 | B4616BA817228DF700863892 /* Frameworks */ = { 114 | isa = PBXFrameworksBuildPhase; 115 | buildActionMask = 2147483647; 116 | files = ( 117 | B4616BAF17228DF700863892 /* UIKit.framework in Frameworks */, 118 | B4616BB117228DF700863892 /* Foundation.framework in Frameworks */, 119 | B4616BB317228DF700863892 /* CoreGraphics.framework in Frameworks */, 120 | ); 121 | runOnlyForDeploymentPostprocessing = 0; 122 | }; 123 | /* End PBXFrameworksBuildPhase section */ 124 | 125 | /* Begin PBXGroup section */ 126 | B435F53D1739811F00297C82 /* Images */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | B44008D8180B11A500D8CB89 /* first_normal.png */, 130 | B44008D9180B11A500D8CB89 /* first_normal@2x.png */, 131 | B44008DA180B11A500D8CB89 /* first_selected.png */, 132 | B44008DB180B11A500D8CB89 /* first_selected@2x.png */, 133 | B407B659182CCA01006F21A6 /* navigationbar_background.png */, 134 | B407B65A182CCA01006F21A6 /* navigationbar_background@2x.png */, 135 | B44008DC180B11A500D8CB89 /* navigationbar_background_tall.png */, 136 | B44008DD180B11A500D8CB89 /* navigationbar_background_tall@2x.png */, 137 | B44008DE180B11A500D8CB89 /* second_normal.png */, 138 | B44008DF180B11A500D8CB89 /* second_normal@2x.png */, 139 | B44008E0180B11A500D8CB89 /* second_selected.png */, 140 | B44008E1180B11A500D8CB89 /* second_selected@2x.png */, 141 | B44008D4180B11A500D8CB89 /* tabbar_normal_background.png */, 142 | B44008D5180B11A500D8CB89 /* tabbar_normal_background@2x.png */, 143 | B44008D6180B11A500D8CB89 /* tabbar_selected_background.png */, 144 | B44008D7180B11A500D8CB89 /* tabbar_selected_background@2x.png */, 145 | B44008F0180B185E00D8CB89 /* third_normal.png */, 146 | B44008F1180B185E00D8CB89 /* third_normal@2x.png */, 147 | B44008F2180B185E00D8CB89 /* third_selected.png */, 148 | B44008F3180B185E00D8CB89 /* third_selected@2x.png */, 149 | ); 150 | path = Images; 151 | sourceTree = ""; 152 | }; 153 | B4616BA217228DF700863892 = { 154 | isa = PBXGroup; 155 | children = ( 156 | B4A742CB176E1BF10055367E /* LICENSE */, 157 | B4A742CC176E1BF10055367E /* README.md */, 158 | B4A63264176F6145004644CA /* Screenshots */, 159 | B4616BB417228DF700863892 /* RDVTabBarController */, 160 | B4616BF4172298E100863892 /* Example */, 161 | B4616BAD17228DF700863892 /* Frameworks */, 162 | B4616BAC17228DF700863892 /* Products */, 163 | ); 164 | sourceTree = ""; 165 | }; 166 | B4616BAC17228DF700863892 /* Products */ = { 167 | isa = PBXGroup; 168 | children = ( 169 | B4616BAB17228DF700863892 /* RDVTabBarController.app */, 170 | ); 171 | name = Products; 172 | sourceTree = ""; 173 | }; 174 | B4616BAD17228DF700863892 /* Frameworks */ = { 175 | isa = PBXGroup; 176 | children = ( 177 | B4616BAE17228DF700863892 /* UIKit.framework */, 178 | B4616BB017228DF700863892 /* Foundation.framework */, 179 | B4616BB217228DF700863892 /* CoreGraphics.framework */, 180 | ); 181 | name = Frameworks; 182 | sourceTree = ""; 183 | }; 184 | B4616BB417228DF700863892 /* RDVTabBarController */ = { 185 | isa = PBXGroup; 186 | children = ( 187 | B435F4F717396A8D00297C82 /* RDVTabBarItem.h */, 188 | B435F4F817396A8D00297C82 /* RDVTabBarItem.m */, 189 | B49817A417229BB500AD294C /* RDVTabBar.h */, 190 | B49817A517229BB500AD294C /* RDVTabBar.m */, 191 | B49817A717229CBC00AD294C /* RDVTabBarController.h */, 192 | B49817A817229CBC00AD294C /* RDVTabBarController.m */, 193 | ); 194 | path = RDVTabBarController; 195 | sourceTree = ""; 196 | }; 197 | B4616BF4172298E100863892 /* Example */ = { 198 | isa = PBXGroup; 199 | children = ( 200 | B4616C071722995D00863892 /* Classes */, 201 | B435F53D1739811F00297C82 /* Images */, 202 | B4616C0D1722996200863892 /* Supporting Files */, 203 | ); 204 | path = Example; 205 | sourceTree = ""; 206 | }; 207 | B4616C071722995D00863892 /* Classes */ = { 208 | isa = PBXGroup; 209 | children = ( 210 | B4616C081722995D00863892 /* App Delegate */, 211 | B4616C0B1722995D00863892 /* Controllers */, 212 | ); 213 | path = Classes; 214 | sourceTree = ""; 215 | }; 216 | B4616C081722995D00863892 /* App Delegate */ = { 217 | isa = PBXGroup; 218 | children = ( 219 | B4616C091722995D00863892 /* RDVAppDelegate.h */, 220 | B4616C0A1722995D00863892 /* RDVAppDelegate.m */, 221 | ); 222 | path = "App Delegate"; 223 | sourceTree = ""; 224 | }; 225 | B4616C0B1722995D00863892 /* Controllers */ = { 226 | isa = PBXGroup; 227 | children = ( 228 | B46573381725A23D00319236 /* RDVFirstViewController.h */, 229 | B46573391725A23D00319236 /* RDVFirstViewController.m */, 230 | B465733B1725A24700319236 /* RDVSecondViewController.h */, 231 | B465733C1725A24700319236 /* RDVSecondViewController.m */, 232 | B465733E1725A25100319236 /* RDVThirdViewController.h */, 233 | B465733F1725A25100319236 /* RDVThirdViewController.m */, 234 | B453D3381A0E2219002F5656 /* RDVDetailsViewController.h */, 235 | B453D3391A0E2219002F5656 /* RDVDetailsViewController.m */, 236 | ); 237 | path = Controllers; 238 | sourceTree = ""; 239 | }; 240 | B4616C0D1722996200863892 /* Supporting Files */ = { 241 | isa = PBXGroup; 242 | children = ( 243 | B4616BF5172298FE00863892 /* Default-568h@2x.png */, 244 | B4616BF6172298FE00863892 /* Default.png */, 245 | B4616BF7172298FE00863892 /* Default@2x.png */, 246 | B4616BF9172298FE00863892 /* InfoPlist.strings */, 247 | B4616BFB172298FE00863892 /* main.m */, 248 | B4616BFE172298FE00863892 /* RDVTabBarController-Info.plist */, 249 | B4616BFF172298FE00863892 /* RDVTabBarController-Prefix.pch */, 250 | B4A37570217CADCC0008264D /* LaunchScreen.storyboard */, 251 | ); 252 | name = "Supporting Files"; 253 | sourceTree = ""; 254 | }; 255 | B4A63264176F6145004644CA /* Screenshots */ = { 256 | isa = PBXGroup; 257 | children = ( 258 | B4A63265176F6145004644CA /* iPad.png */, 259 | B4DB369F182C4B7C0008898E /* iPad-small.png */, 260 | B4A63266176F6145004644CA /* iPhone.png */, 261 | B4DB36A0182C4B7C0008898E /* iPhone-small.png */, 262 | ); 263 | path = Screenshots; 264 | sourceTree = ""; 265 | }; 266 | /* End PBXGroup section */ 267 | 268 | /* Begin PBXNativeTarget section */ 269 | B4616BAA17228DF700863892 /* RDVTabBarController */ = { 270 | isa = PBXNativeTarget; 271 | buildConfigurationList = B4616BC817228DF700863892 /* Build configuration list for PBXNativeTarget "RDVTabBarController" */; 272 | buildPhases = ( 273 | B4616BA717228DF700863892 /* Sources */, 274 | B4616BA817228DF700863892 /* Frameworks */, 275 | B4616BA917228DF700863892 /* Resources */, 276 | ); 277 | buildRules = ( 278 | ); 279 | dependencies = ( 280 | ); 281 | name = RDVTabBarController; 282 | productName = RDVTabBarController; 283 | productReference = B4616BAB17228DF700863892 /* RDVTabBarController.app */; 284 | productType = "com.apple.product-type.application"; 285 | }; 286 | /* End PBXNativeTarget section */ 287 | 288 | /* Begin PBXProject section */ 289 | B4616BA317228DF700863892 /* Project object */ = { 290 | isa = PBXProject; 291 | attributes = { 292 | CLASSPREFIX = RDV; 293 | LastUpgradeCheck = 1100; 294 | ORGANIZATIONNAME = "Robert Dimitrov"; 295 | TargetAttributes = { 296 | B4616BAA17228DF700863892 = { 297 | ProvisioningStyle = Automatic; 298 | }; 299 | }; 300 | }; 301 | buildConfigurationList = B4616BA617228DF700863892 /* Build configuration list for PBXProject "RDVTabBarController" */; 302 | compatibilityVersion = "Xcode 3.2"; 303 | developmentRegion = en; 304 | hasScannedForEncodings = 0; 305 | knownRegions = ( 306 | en, 307 | Base, 308 | ); 309 | mainGroup = B4616BA217228DF700863892; 310 | productRefGroup = B4616BAC17228DF700863892 /* Products */; 311 | projectDirPath = ""; 312 | projectRoot = ""; 313 | targets = ( 314 | B4616BAA17228DF700863892 /* RDVTabBarController */, 315 | ); 316 | }; 317 | /* End PBXProject section */ 318 | 319 | /* Begin PBXResourcesBuildPhase section */ 320 | B4616BA917228DF700863892 /* Resources */ = { 321 | isa = PBXResourcesBuildPhase; 322 | buildActionMask = 2147483647; 323 | files = ( 324 | B44008EE180B11A500D8CB89 /* second_selected.png in Resources */, 325 | B4616C00172298FE00863892 /* Default-568h@2x.png in Resources */, 326 | B4616C01172298FE00863892 /* Default.png in Resources */, 327 | B44008EA180B11A500D8CB89 /* navigationbar_background_tall.png in Resources */, 328 | B4DB36A2182C4B7C0008898E /* iPhone-small.png in Resources */, 329 | B4DB36A1182C4B7C0008898E /* iPad-small.png in Resources */, 330 | B44008E9180B11A500D8CB89 /* first_selected@2x.png in Resources */, 331 | B44008E7180B11A500D8CB89 /* first_normal@2x.png in Resources */, 332 | B407B65C182CCA01006F21A6 /* navigationbar_background@2x.png in Resources */, 333 | B407B65B182CCA01006F21A6 /* navigationbar_background.png in Resources */, 334 | B44008F6180B185E00D8CB89 /* third_selected.png in Resources */, 335 | B4616C02172298FE00863892 /* Default@2x.png in Resources */, 336 | B44008E4180B11A500D8CB89 /* tabbar_selected_background.png in Resources */, 337 | B44008F7180B185E00D8CB89 /* third_selected@2x.png in Resources */, 338 | B44008E3180B11A500D8CB89 /* tabbar_normal_background@2x.png in Resources */, 339 | B44008EC180B11A500D8CB89 /* second_normal.png in Resources */, 340 | B44008E8180B11A500D8CB89 /* first_selected.png in Resources */, 341 | B44008F5180B185E00D8CB89 /* third_normal@2x.png in Resources */, 342 | B4616C03172298FE00863892 /* InfoPlist.strings in Resources */, 343 | B4A742CD176E1BF10055367E /* LICENSE in Resources */, 344 | B44008EB180B11A500D8CB89 /* navigationbar_background_tall@2x.png in Resources */, 345 | B44008ED180B11A500D8CB89 /* second_normal@2x.png in Resources */, 346 | B44008EF180B11A500D8CB89 /* second_selected@2x.png in Resources */, 347 | B44008E5180B11A500D8CB89 /* tabbar_selected_background@2x.png in Resources */, 348 | B4A742CE176E1BF10055367E /* README.md in Resources */, 349 | B4A63267176F6145004644CA /* iPad.png in Resources */, 350 | B4A37571217CADCC0008264D /* LaunchScreen.storyboard in Resources */, 351 | B4A63268176F6145004644CA /* iPhone.png in Resources */, 352 | B44008E2180B11A500D8CB89 /* tabbar_normal_background.png in Resources */, 353 | B44008E6180B11A500D8CB89 /* first_normal.png in Resources */, 354 | B44008F4180B185E00D8CB89 /* third_normal.png in Resources */, 355 | ); 356 | runOnlyForDeploymentPostprocessing = 0; 357 | }; 358 | /* End PBXResourcesBuildPhase section */ 359 | 360 | /* Begin PBXSourcesBuildPhase section */ 361 | B4616BA717228DF700863892 /* Sources */ = { 362 | isa = PBXSourcesBuildPhase; 363 | buildActionMask = 2147483647; 364 | files = ( 365 | B4616C04172298FE00863892 /* main.m in Sources */, 366 | B4616C0C1722995D00863892 /* RDVAppDelegate.m in Sources */, 367 | B49817A617229BB500AD294C /* RDVTabBar.m in Sources */, 368 | B453D33A1A0E2219002F5656 /* RDVDetailsViewController.m in Sources */, 369 | B49817A917229CBC00AD294C /* RDVTabBarController.m in Sources */, 370 | B465733A1725A23D00319236 /* RDVFirstViewController.m in Sources */, 371 | B465733D1725A24700319236 /* RDVSecondViewController.m in Sources */, 372 | B46573401725A25100319236 /* RDVThirdViewController.m in Sources */, 373 | B435F4F917396A8D00297C82 /* RDVTabBarItem.m in Sources */, 374 | ); 375 | runOnlyForDeploymentPostprocessing = 0; 376 | }; 377 | /* End PBXSourcesBuildPhase section */ 378 | 379 | /* Begin PBXVariantGroup section */ 380 | B4616BF9172298FE00863892 /* InfoPlist.strings */ = { 381 | isa = PBXVariantGroup; 382 | children = ( 383 | B4616BFA172298FE00863892 /* en */, 384 | ); 385 | name = InfoPlist.strings; 386 | path = en.lproj; 387 | sourceTree = ""; 388 | }; 389 | /* End PBXVariantGroup section */ 390 | 391 | /* Begin XCBuildConfiguration section */ 392 | B4616BC617228DF700863892 /* Debug */ = { 393 | isa = XCBuildConfiguration; 394 | buildSettings = { 395 | ALWAYS_SEARCH_USER_PATHS = NO; 396 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 397 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 398 | CLANG_CXX_LIBRARY = "libc++"; 399 | CLANG_ENABLE_OBJC_ARC = YES; 400 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 401 | CLANG_WARN_BOOL_CONVERSION = YES; 402 | CLANG_WARN_COMMA = YES; 403 | CLANG_WARN_CONSTANT_CONVERSION = YES; 404 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 405 | CLANG_WARN_EMPTY_BODY = YES; 406 | CLANG_WARN_ENUM_CONVERSION = YES; 407 | CLANG_WARN_INFINITE_RECURSION = YES; 408 | CLANG_WARN_INT_CONVERSION = YES; 409 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 410 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 411 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 412 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 413 | CLANG_WARN_STRICT_PROTOTYPES = YES; 414 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 415 | CLANG_WARN_UNREACHABLE_CODE = YES; 416 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 417 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 418 | COPY_PHASE_STRIP = NO; 419 | ENABLE_STRICT_OBJC_MSGSEND = YES; 420 | ENABLE_TESTABILITY = YES; 421 | GCC_C_LANGUAGE_STANDARD = gnu99; 422 | GCC_DYNAMIC_NO_PIC = NO; 423 | GCC_NO_COMMON_BLOCKS = YES; 424 | GCC_OPTIMIZATION_LEVEL = 0; 425 | GCC_PREPROCESSOR_DEFINITIONS = ( 426 | "DEBUG=1", 427 | "$(inherited)", 428 | ); 429 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 430 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 431 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 432 | GCC_WARN_UNDECLARED_SELECTOR = YES; 433 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 434 | GCC_WARN_UNUSED_FUNCTION = YES; 435 | GCC_WARN_UNUSED_VARIABLE = YES; 436 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 437 | ONLY_ACTIVE_ARCH = YES; 438 | SDKROOT = iphoneos; 439 | TARGETED_DEVICE_FAMILY = "1,2"; 440 | }; 441 | name = Debug; 442 | }; 443 | B4616BC717228DF700863892 /* Release */ = { 444 | isa = XCBuildConfiguration; 445 | buildSettings = { 446 | ALWAYS_SEARCH_USER_PATHS = NO; 447 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 448 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 449 | CLANG_CXX_LIBRARY = "libc++"; 450 | CLANG_ENABLE_OBJC_ARC = YES; 451 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 452 | CLANG_WARN_BOOL_CONVERSION = YES; 453 | CLANG_WARN_COMMA = YES; 454 | CLANG_WARN_CONSTANT_CONVERSION = YES; 455 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 456 | CLANG_WARN_EMPTY_BODY = YES; 457 | CLANG_WARN_ENUM_CONVERSION = YES; 458 | CLANG_WARN_INFINITE_RECURSION = YES; 459 | CLANG_WARN_INT_CONVERSION = YES; 460 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 461 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 462 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 463 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 464 | CLANG_WARN_STRICT_PROTOTYPES = YES; 465 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 466 | CLANG_WARN_UNREACHABLE_CODE = YES; 467 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 468 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 469 | COPY_PHASE_STRIP = YES; 470 | ENABLE_STRICT_OBJC_MSGSEND = YES; 471 | GCC_C_LANGUAGE_STANDARD = gnu99; 472 | GCC_NO_COMMON_BLOCKS = YES; 473 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 474 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 475 | GCC_WARN_UNDECLARED_SELECTOR = YES; 476 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 477 | GCC_WARN_UNUSED_FUNCTION = YES; 478 | GCC_WARN_UNUSED_VARIABLE = YES; 479 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 480 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 481 | SDKROOT = iphoneos; 482 | TARGETED_DEVICE_FAMILY = "1,2"; 483 | VALIDATE_PRODUCT = YES; 484 | }; 485 | name = Release; 486 | }; 487 | B4616BC917228DF700863892 /* Debug */ = { 488 | isa = XCBuildConfiguration; 489 | buildSettings = { 490 | CODE_SIGN_IDENTITY = "Apple Development"; 491 | CODE_SIGN_STYLE = Automatic; 492 | DEVELOPMENT_TEAM = ""; 493 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 494 | GCC_PREFIX_HEADER = "Example/RDVTabBarController-Prefix.pch"; 495 | INFOPLIST_FILE = "$(SRCROOT)/Example/RDVTabBarController-Info.plist"; 496 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 497 | PRODUCT_BUNDLE_IDENTIFIER = "com.robbdimitrov.${PRODUCT_NAME:rfc1034identifier}"; 498 | PRODUCT_NAME = "$(TARGET_NAME)"; 499 | PROVISIONING_PROFILE_SPECIFIER = ""; 500 | WRAPPER_EXTENSION = app; 501 | }; 502 | name = Debug; 503 | }; 504 | B4616BCA17228DF700863892 /* Release */ = { 505 | isa = XCBuildConfiguration; 506 | buildSettings = { 507 | CODE_SIGN_IDENTITY = "Apple Development"; 508 | CODE_SIGN_STYLE = Automatic; 509 | DEVELOPMENT_TEAM = ""; 510 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 511 | GCC_PREFIX_HEADER = "Example/RDVTabBarController-Prefix.pch"; 512 | INFOPLIST_FILE = "$(SRCROOT)/Example/RDVTabBarController-Info.plist"; 513 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 514 | PRODUCT_BUNDLE_IDENTIFIER = "com.robbdimitrov.${PRODUCT_NAME:rfc1034identifier}"; 515 | PRODUCT_NAME = "$(TARGET_NAME)"; 516 | PROVISIONING_PROFILE_SPECIFIER = ""; 517 | WRAPPER_EXTENSION = app; 518 | }; 519 | name = Release; 520 | }; 521 | /* End XCBuildConfiguration section */ 522 | 523 | /* Begin XCConfigurationList section */ 524 | B4616BA617228DF700863892 /* Build configuration list for PBXProject "RDVTabBarController" */ = { 525 | isa = XCConfigurationList; 526 | buildConfigurations = ( 527 | B4616BC617228DF700863892 /* Debug */, 528 | B4616BC717228DF700863892 /* Release */, 529 | ); 530 | defaultConfigurationIsVisible = 0; 531 | defaultConfigurationName = Release; 532 | }; 533 | B4616BC817228DF700863892 /* Build configuration list for PBXNativeTarget "RDVTabBarController" */ = { 534 | isa = XCConfigurationList; 535 | buildConfigurations = ( 536 | B4616BC917228DF700863892 /* Debug */, 537 | B4616BCA17228DF700863892 /* Release */, 538 | ); 539 | defaultConfigurationIsVisible = 0; 540 | defaultConfigurationName = Release; 541 | }; 542 | /* End XCConfigurationList section */ 543 | }; 544 | rootObject = B4616BA317228DF700863892 /* Project object */; 545 | } 546 | -------------------------------------------------------------------------------- /RDVTabBarController.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /RDVTabBarController/RDVTabBar.h: -------------------------------------------------------------------------------- 1 | // RDVTabBar.h 2 | // RDVTabBarController 3 | // 4 | // Copyright (c) 2013 Robert Dimitrov 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #import 25 | 26 | @class RDVTabBar, RDVTabBarItem; 27 | 28 | @protocol RDVTabBarDelegate 29 | 30 | /** 31 | * Asks the delegate if the specified tab bar item should be selected. 32 | */ 33 | - (BOOL)tabBar:(RDVTabBar *)tabBar shouldSelectItemAtIndex:(NSInteger)index; 34 | 35 | /** 36 | * Tells the delegate that the specified tab bar item is now selected. 37 | */ 38 | - (void)tabBar:(RDVTabBar *)tabBar didSelectItemAtIndex:(NSInteger)index; 39 | 40 | @end 41 | 42 | @interface RDVTabBar : UIView 43 | 44 | /** 45 | * The tab bar’s delegate object. 46 | */ 47 | @property (nonatomic, weak) id delegate; 48 | 49 | /** 50 | * The items displayed on the tab bar. 51 | */ 52 | @property (nonatomic, copy) NSArray *items; 53 | 54 | /** 55 | * The currently selected item on the tab bar. 56 | */ 57 | @property (nonatomic, weak) RDVTabBarItem *selectedItem; 58 | 59 | /** 60 | * backgroundView stays behind tabBar's items. If you want to add additional views, 61 | * add them as subviews of backgroundView. 62 | */ 63 | @property (nonatomic, readonly) UIView *backgroundView; 64 | 65 | /* 66 | * contentEdgeInsets can be used to center the items in the middle of the tabBar. 67 | */ 68 | @property UIEdgeInsets contentEdgeInsets; 69 | 70 | /** 71 | * Sets the height of tab bar. 72 | */ 73 | - (void)setHeight:(CGFloat)height; 74 | 75 | /** 76 | * Returns the minimum height of tab bar's items. 77 | */ 78 | - (CGFloat)minimumContentHeight; 79 | 80 | /* 81 | * Enable or disable tabBar translucency. Default is NO. 82 | */ 83 | @property (nonatomic, getter=isTranslucent) BOOL translucent; 84 | 85 | @end 86 | -------------------------------------------------------------------------------- /RDVTabBarController/RDVTabBar.m: -------------------------------------------------------------------------------- 1 | // RDVTabBar.m 2 | // RDVTabBarController 3 | // 4 | // Copyright (c) 2013 Robert Dimitrov 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #import "RDVTabBar.h" 25 | #import "RDVTabBarItem.h" 26 | 27 | @interface RDVTabBar () 28 | 29 | @property (nonatomic) CGFloat itemWidth; 30 | @property (nonatomic) UIView *backgroundView; 31 | 32 | @end 33 | 34 | @implementation RDVTabBar 35 | 36 | - (id)initWithFrame:(CGRect)frame { 37 | self = [super initWithFrame:frame]; 38 | if (self) { 39 | [self commonInitialization]; 40 | } 41 | return self; 42 | } 43 | 44 | - (id)initWithCoder:(NSCoder *)aDecoder { 45 | self = [super initWithCoder:aDecoder]; 46 | if (self) { 47 | [self commonInitialization]; 48 | } 49 | return self; 50 | } 51 | 52 | - (id)init { 53 | return [self initWithFrame:CGRectZero]; 54 | } 55 | 56 | - (void)commonInitialization { 57 | _backgroundView = [[UIView alloc] init]; 58 | [self addSubview:_backgroundView]; 59 | 60 | [self setTranslucent:NO]; 61 | } 62 | 63 | - (void)layoutSubviews { 64 | CGSize frameSize = self.frame.size; 65 | CGFloat minimumContentHeight = [self minimumContentHeight]; 66 | 67 | [[self backgroundView] setFrame:CGRectMake(0, frameSize.height - minimumContentHeight, 68 | frameSize.width, frameSize.height)]; 69 | 70 | [self setItemWidth:roundf((frameSize.width - [self contentEdgeInsets].left - 71 | [self contentEdgeInsets].right) / [[self items] count])]; 72 | 73 | NSInteger index = 0; 74 | 75 | // Layout items 76 | 77 | for (RDVTabBarItem *item in [self items]) { 78 | CGFloat itemHeight = [item itemHeight]; 79 | 80 | if (!itemHeight) { 81 | itemHeight = frameSize.height; 82 | } 83 | 84 | [item setFrame:CGRectMake(self.contentEdgeInsets.left + (index * self.itemWidth), 85 | roundf(frameSize.height - itemHeight) - self.contentEdgeInsets.top, 86 | self.itemWidth, itemHeight - self.contentEdgeInsets.bottom)]; 87 | [item setNeedsDisplay]; 88 | 89 | index++; 90 | } 91 | } 92 | 93 | #pragma mark - Configuration 94 | 95 | - (void)setItemWidth:(CGFloat)itemWidth { 96 | if (itemWidth > 0) { 97 | _itemWidth = itemWidth; 98 | } 99 | } 100 | 101 | - (void)setItems:(NSArray *)items { 102 | for (RDVTabBarItem *item in _items) { 103 | [item removeFromSuperview]; 104 | } 105 | 106 | _items = [items copy]; 107 | for (RDVTabBarItem *item in _items) { 108 | [item addTarget:self action:@selector(tabBarItemWasSelected:) forControlEvents:UIControlEventTouchDown]; 109 | [self addSubview:item]; 110 | } 111 | } 112 | 113 | - (void)setHeight:(CGFloat)height { 114 | [self setFrame:CGRectMake(CGRectGetMinX(self.frame), CGRectGetMinY(self.frame), 115 | CGRectGetWidth(self.frame), height)]; 116 | } 117 | 118 | - (CGFloat)minimumContentHeight { 119 | CGFloat minimumTabBarContentHeight = CGRectGetHeight([self frame]); 120 | 121 | for (RDVTabBarItem *item in [self items]) { 122 | CGFloat itemHeight = [item itemHeight]; 123 | if (itemHeight && (itemHeight < minimumTabBarContentHeight)) { 124 | minimumTabBarContentHeight = itemHeight; 125 | } 126 | } 127 | 128 | return minimumTabBarContentHeight; 129 | } 130 | 131 | #pragma mark - Item selection 132 | 133 | - (void)tabBarItemWasSelected:(id)sender { 134 | if ([[self delegate] respondsToSelector:@selector(tabBar:shouldSelectItemAtIndex:)]) { 135 | NSInteger index = [self.items indexOfObject:sender]; 136 | if (![[self delegate] tabBar:self shouldSelectItemAtIndex:index]) { 137 | return; 138 | } 139 | } 140 | 141 | [self setSelectedItem:sender]; 142 | 143 | if ([[self delegate] respondsToSelector:@selector(tabBar:didSelectItemAtIndex:)]) { 144 | NSInteger index = [self.items indexOfObject:self.selectedItem]; 145 | [[self delegate] tabBar:self didSelectItemAtIndex:index]; 146 | } 147 | } 148 | 149 | - (void)setSelectedItem:(RDVTabBarItem *)selectedItem { 150 | if (selectedItem == _selectedItem) { 151 | return; 152 | } 153 | [_selectedItem setSelected:NO]; 154 | 155 | _selectedItem = selectedItem; 156 | [_selectedItem setSelected:YES]; 157 | } 158 | 159 | #pragma mark - Translucency 160 | 161 | - (void)setTranslucent:(BOOL)translucent { 162 | _translucent = translucent; 163 | 164 | CGFloat alpha = (translucent ? 0.9 : 1.0); 165 | 166 | [_backgroundView setBackgroundColor:[UIColor colorWithRed:245/255.0 167 | green:245/255.0 168 | blue:245/255.0 169 | alpha:alpha]]; 170 | } 171 | 172 | #pragma mark - Accessibility 173 | 174 | - (BOOL)isAccessibilityElement{ 175 | return NO; 176 | } 177 | 178 | - (NSInteger)accessibilityElementCount{ 179 | return self.items.count; 180 | } 181 | 182 | - (id)accessibilityElementAtIndex:(NSInteger)index{ 183 | return self.items[index]; 184 | } 185 | 186 | - (NSInteger)indexOfAccessibilityElement:(id)element{ 187 | return [self.items indexOfObject:element]; 188 | } 189 | 190 | @end 191 | -------------------------------------------------------------------------------- /RDVTabBarController/RDVTabBarController.h: -------------------------------------------------------------------------------- 1 | // RDVTabBarController.h 2 | // RDVTabBarController 3 | // 4 | // Copyright (c) 2013 Robert Dimitrov 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #import 25 | #import "RDVTabBar.h" 26 | 27 | @protocol RDVTabBarControllerDelegate; 28 | 29 | @interface RDVTabBarController : UIViewController 30 | 31 | /** 32 | * The tab bar controller’s delegate object. 33 | */ 34 | @property (nonatomic, weak) id delegate; 35 | 36 | /** 37 | * An array of the root view controllers displayed by the tab bar interface. 38 | */ 39 | @property (nonatomic, copy) IBOutletCollection(UIViewController) NSArray *viewControllers; 40 | 41 | /** 42 | * The tab bar view associated with this controller. (read-only) 43 | */ 44 | @property (nonatomic, readonly) RDVTabBar *tabBar; 45 | 46 | /** 47 | * The view controller associated with the currently selected tab item. 48 | */ 49 | @property (nonatomic, weak) UIViewController *selectedViewController; 50 | 51 | /** 52 | * The index of the view controller associated with the currently selected tab item. 53 | */ 54 | @property (nonatomic) NSUInteger selectedIndex; 55 | 56 | /** 57 | * A Boolean value that determines whether the tab bar is hidden. 58 | */ 59 | @property (nonatomic, getter=isTabBarHidden) BOOL tabBarHidden; 60 | 61 | /** 62 | * Changes the visibility of the tab bar. 63 | */ 64 | - (void)setTabBarHidden:(BOOL)hidden animated:(BOOL)animated; 65 | 66 | @end 67 | 68 | @protocol RDVTabBarControllerDelegate 69 | @optional 70 | /** 71 | * Asks the delegate whether the specified view controller should be made active. 72 | */ 73 | - (BOOL)tabBarController:(RDVTabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController; 74 | 75 | /** 76 | * Tells the delegate that the user selected an item in the tab bar. 77 | */ 78 | - (void)tabBarController:(RDVTabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController; 79 | 80 | /** 81 | * Tells the delegate that the user tap on the selected item in the tab bar. 82 | */ 83 | - (void)tabBarController:(RDVTabBarController *)tabBarController didSelectItemAtIndex:(NSInteger)index; 84 | 85 | @end 86 | 87 | @interface UIViewController (RDVTabBarControllerItem) 88 | 89 | /** 90 | * The tab bar item that represents the view controller when added to a tab bar controller. 91 | */ 92 | @property(nonatomic, setter = rdv_setTabBarItem:) RDVTabBarItem *rdv_tabBarItem; 93 | 94 | /** 95 | * The nearest ancestor in the view controller hierarchy that is a tab bar controller. (read-only) 96 | */ 97 | @property(nonatomic, readonly) RDVTabBarController *rdv_tabBarController; 98 | 99 | @end 100 | -------------------------------------------------------------------------------- /RDVTabBarController/RDVTabBarController.m: -------------------------------------------------------------------------------- 1 | // RDVTabBarController.m 2 | // RDVTabBarController 3 | // 4 | // Copyright (c) 2013 Robert Dimitrov 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #import "RDVTabBarController.h" 25 | #import "RDVTabBarItem.h" 26 | #import 27 | 28 | @interface UIViewController (RDVTabBarControllerItemInternal) 29 | 30 | - (void)rdv_setTabBarController:(RDVTabBarController *)tabBarController; 31 | 32 | @end 33 | 34 | @interface RDVTabBarController () { 35 | UIView *_contentView; 36 | } 37 | 38 | @property (nonatomic, readwrite) RDVTabBar *tabBar; 39 | 40 | @end 41 | 42 | @implementation RDVTabBarController 43 | 44 | #pragma mark - View lifecycle 45 | 46 | - (void)viewDidLoad { 47 | [super viewDidLoad]; 48 | 49 | [self.view addSubview:[self contentView]]; 50 | [self.view addSubview:[self tabBar]]; 51 | } 52 | 53 | - (void)viewWillAppear:(BOOL)animated { 54 | [super viewWillAppear:animated]; 55 | 56 | [self setSelectedIndex:[self selectedIndex]]; 57 | } 58 | 59 | -(void)viewDidLayoutSubviews{ 60 | [super viewDidLayoutSubviews]; 61 | 62 | CGSize viewSize = self.view.bounds.size; 63 | CGFloat tabBarStartingY = viewSize.height; 64 | CGFloat contentViewHeight = viewSize.height; 65 | CGFloat tabBarHeight = CGRectGetHeight([[self tabBar] frame]); 66 | 67 | if (!tabBarHeight) { 68 | if (@available(iOS 11.0, *)) { 69 | CGFloat safeAreaBottom = UIApplication.sharedApplication.keyWindow.safeAreaInsets.bottom; 70 | tabBarHeight = 58.f + safeAreaBottom / 1.5f; 71 | } else { 72 | tabBarHeight = 58.f; 73 | } 74 | } else if (@available(iOS 11.0, *)) { 75 | CGFloat safeAreaBottom = UIApplication.sharedApplication.keyWindow.safeAreaInsets.bottom; 76 | tabBarHeight = 58.f + safeAreaBottom / 1.5f; 77 | } 78 | 79 | if (!self.tabBarHidden) { 80 | tabBarStartingY = viewSize.height - tabBarHeight; 81 | if (![[self tabBar] isTranslucent]) { 82 | contentViewHeight -= ([[self tabBar] minimumContentHeight] ?: tabBarHeight); 83 | } 84 | } 85 | 86 | [[self tabBar] setFrame:CGRectMake(0, tabBarStartingY, viewSize.width, tabBarHeight)]; 87 | [[self contentView] setFrame:CGRectMake(0, 0, viewSize.width, contentViewHeight)]; 88 | [[[self selectedViewController] view] setFrame:[[self contentView] bounds]]; 89 | } 90 | 91 | - (UIStatusBarStyle)preferredStatusBarStyle { 92 | return self.selectedViewController.preferredStatusBarStyle; 93 | } 94 | 95 | - (UIStatusBarAnimation)preferredStatusBarUpdateAnimation { 96 | return self.selectedViewController.preferredStatusBarUpdateAnimation; 97 | } 98 | 99 | - (UIInterfaceOrientationMask)supportedInterfaceOrientations { 100 | UIInterfaceOrientationMask orientationMask = UIInterfaceOrientationMaskAll; 101 | for (UIViewController *viewController in [self viewControllers]) { 102 | if (![viewController respondsToSelector:@selector(supportedInterfaceOrientations)]) { 103 | return UIInterfaceOrientationMaskPortrait; 104 | } 105 | 106 | UIInterfaceOrientationMask supportedOrientations = [viewController supportedInterfaceOrientations]; 107 | 108 | if (orientationMask > supportedOrientations) { 109 | orientationMask = supportedOrientations; 110 | } 111 | } 112 | 113 | return orientationMask; 114 | } 115 | 116 | #pragma mark - Methods 117 | 118 | - (UIViewController *)selectedViewController { 119 | return [[self viewControllers] objectAtIndex:[self selectedIndex]]; 120 | } 121 | 122 | - (void)setSelectedIndex:(NSUInteger)selectedIndex { 123 | if (selectedIndex >= self.viewControllers.count) { 124 | return; 125 | } 126 | 127 | if ([self selectedViewController]) { 128 | [[self selectedViewController] willMoveToParentViewController:nil]; 129 | [[[self selectedViewController] view] removeFromSuperview]; 130 | [[self selectedViewController] removeFromParentViewController]; 131 | } 132 | 133 | _selectedIndex = selectedIndex; 134 | [[self tabBar] setSelectedItem:[[self tabBar] items][selectedIndex]]; 135 | 136 | [self setSelectedViewController:[[self viewControllers] objectAtIndex:selectedIndex]]; 137 | [self addChildViewController:[self selectedViewController]]; 138 | [[[self selectedViewController] view] setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight]; 139 | [[self contentView] addSubview:[[self selectedViewController] view]]; 140 | [[self selectedViewController] didMoveToParentViewController:self]; 141 | 142 | [self.view setNeedsLayout]; 143 | [self setNeedsStatusBarAppearanceUpdate]; 144 | } 145 | 146 | - (void)setViewControllers:(NSArray *)viewControllers { 147 | if (_viewControllers && _viewControllers.count) { 148 | for (UIViewController *viewController in _viewControllers) { 149 | [viewController willMoveToParentViewController:nil]; 150 | [viewController.view removeFromSuperview]; 151 | [viewController removeFromParentViewController]; 152 | } 153 | } 154 | 155 | if (viewControllers && [viewControllers isKindOfClass:[NSArray class]]) { 156 | _viewControllers = [viewControllers copy]; 157 | 158 | NSMutableArray *tabBarItems = [[NSMutableArray alloc] init]; 159 | 160 | for (UIViewController *viewController in viewControllers) { 161 | RDVTabBarItem *tabBarItem = [[RDVTabBarItem alloc] init]; 162 | [tabBarItem setTitle:viewController.title]; 163 | [tabBarItems addObject:tabBarItem]; 164 | [viewController rdv_setTabBarController:self]; 165 | } 166 | 167 | [[self tabBar] setItems:tabBarItems]; 168 | } else { 169 | for (UIViewController *viewController in _viewControllers) { 170 | [viewController rdv_setTabBarController:nil]; 171 | } 172 | 173 | _viewControllers = nil; 174 | } 175 | } 176 | 177 | - (NSInteger)indexForViewController:(UIViewController *)viewController { 178 | UIViewController *searchedController = viewController; 179 | while (searchedController.parentViewController != nil && searchedController.parentViewController != self) { 180 | searchedController = searchedController.parentViewController; 181 | } 182 | return [[self viewControllers] indexOfObject:searchedController]; 183 | } 184 | 185 | - (RDVTabBar *)tabBar { 186 | if (!_tabBar) { 187 | _tabBar = [[RDVTabBar alloc] init]; 188 | [_tabBar setBackgroundColor:[UIColor clearColor]]; 189 | [_tabBar setAutoresizingMask:(UIViewAutoresizingFlexibleWidth| 190 | UIViewAutoresizingFlexibleTopMargin| 191 | UIViewAutoresizingFlexibleLeftMargin| 192 | UIViewAutoresizingFlexibleRightMargin| 193 | UIViewAutoresizingFlexibleBottomMargin)]; 194 | [_tabBar setDelegate:self]; 195 | } 196 | return _tabBar; 197 | } 198 | 199 | - (UIView *)contentView { 200 | if (!_contentView) { 201 | _contentView = [[UIView alloc] init]; 202 | [_contentView setBackgroundColor:[UIColor whiteColor]]; 203 | [_contentView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth| 204 | UIViewAutoresizingFlexibleHeight)]; 205 | } 206 | return _contentView; 207 | } 208 | 209 | - (void)setTabBarHidden:(BOOL)hidden animated:(BOOL)animated { 210 | // make sure any pending layout is done, to prevent spurious animations 211 | [self.view layoutIfNeeded]; 212 | 213 | _tabBarHidden = hidden; 214 | 215 | [self.view setNeedsLayout]; 216 | 217 | if (!_tabBarHidden) { 218 | [[self tabBar] setHidden:NO]; 219 | } 220 | 221 | [UIView animateWithDuration:(animated ? 0.24 : 0) animations:^{ 222 | [self.view layoutIfNeeded]; 223 | } completion:^(BOOL finished){ 224 | if (self.tabBarHidden) { 225 | [[self tabBar] setHidden:YES]; 226 | } 227 | }]; 228 | } 229 | 230 | - (void)setTabBarHidden:(BOOL)hidden { 231 | [self setTabBarHidden:hidden animated:NO]; 232 | } 233 | 234 | #pragma mark - RDVTabBarDelegate 235 | 236 | - (BOOL)tabBar:(RDVTabBar *)tabBar shouldSelectItemAtIndex:(NSInteger)index { 237 | if ([[self delegate] respondsToSelector:@selector(tabBarController:shouldSelectViewController:)]) { 238 | if (![[self delegate] tabBarController:self shouldSelectViewController:[self viewControllers][index]]) { 239 | return NO; 240 | } 241 | } 242 | 243 | if ([self selectedViewController] == [self viewControllers][index]) { 244 | if ([[self delegate] respondsToSelector:@selector(tabBarController:didSelectItemAtIndex:)]) { 245 | [[self delegate] tabBarController:self didSelectItemAtIndex:index]; 246 | } 247 | 248 | if ([[self selectedViewController] isKindOfClass:[UINavigationController class]]) { 249 | UINavigationController *selectedController = (UINavigationController *)[self selectedViewController]; 250 | 251 | if ([selectedController topViewController] != [selectedController viewControllers][0]) { 252 | [selectedController popToRootViewControllerAnimated:YES]; 253 | } 254 | } 255 | 256 | return NO; 257 | } 258 | 259 | return YES; 260 | } 261 | 262 | - (void)tabBar:(RDVTabBar *)tabBar didSelectItemAtIndex:(NSInteger)index { 263 | if (index < 0 || index >= [[self viewControllers] count]) { 264 | return; 265 | } 266 | 267 | [self setSelectedIndex:index]; 268 | 269 | if ([[self delegate] respondsToSelector:@selector(tabBarController:didSelectViewController:)]) { 270 | [[self delegate] tabBarController:self didSelectViewController:[self viewControllers][index]]; 271 | } 272 | } 273 | 274 | @end 275 | 276 | #pragma mark - UIViewController+RDVTabBarControllerItem 277 | 278 | @implementation UIViewController (RDVTabBarControllerItemInternal) 279 | 280 | - (void)rdv_setTabBarController:(RDVTabBarController *)tabBarController { 281 | objc_setAssociatedObject(self, @selector(rdv_tabBarController), tabBarController, OBJC_ASSOCIATION_ASSIGN); 282 | } 283 | 284 | @end 285 | 286 | @implementation UIViewController (RDVTabBarControllerItem) 287 | 288 | - (RDVTabBarController *)rdv_tabBarController { 289 | RDVTabBarController *tabBarController = objc_getAssociatedObject(self, @selector(rdv_tabBarController)); 290 | 291 | if (!tabBarController && self.parentViewController) { 292 | tabBarController = [self.parentViewController rdv_tabBarController]; 293 | } 294 | 295 | return tabBarController; 296 | } 297 | 298 | - (RDVTabBarItem *)rdv_tabBarItem { 299 | RDVTabBarController *tabBarController = [self rdv_tabBarController]; 300 | NSInteger index = [tabBarController indexForViewController:self]; 301 | return [[[tabBarController tabBar] items] objectAtIndex:index]; 302 | } 303 | 304 | - (void)rdv_setTabBarItem:(RDVTabBarItem *)tabBarItem { 305 | RDVTabBarController *tabBarController = [self rdv_tabBarController]; 306 | 307 | if (!tabBarController) { 308 | return; 309 | } 310 | 311 | RDVTabBar *tabBar = [tabBarController tabBar]; 312 | NSInteger index = [tabBarController indexForViewController:self]; 313 | 314 | NSMutableArray *tabBarItems = [[NSMutableArray alloc] initWithArray:[tabBar items]]; 315 | [tabBarItems replaceObjectAtIndex:index withObject:tabBarItem]; 316 | [tabBar setItems:tabBarItems]; 317 | } 318 | 319 | @end 320 | -------------------------------------------------------------------------------- /RDVTabBarController/RDVTabBarItem.h: -------------------------------------------------------------------------------- 1 | // RDVTabBarItem.h 2 | // RDVTabBarController 3 | // 4 | // Copyright (c) 2013 Robert Dimitrov 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #import 25 | 26 | @interface RDVTabBarItem : UIControl 27 | 28 | /** 29 | * itemHeight is an optional property. When set it is used instead of tabBar's height. 30 | */ 31 | @property CGFloat itemHeight; 32 | 33 | #pragma mark - Title configuration 34 | 35 | /** 36 | * The title displayed by the tab bar item. 37 | */ 38 | @property (nonatomic, copy) NSString *title; 39 | 40 | /** 41 | * The offset for the rectangle around the tab bar item's title. 42 | */ 43 | @property (nonatomic) UIOffset titlePositionAdjustment; 44 | 45 | /** 46 | * For title's text attributes see 47 | * https://developer.apple.com/library/ios/documentation/uikit/reference/NSString_UIKit_Additions/Reference/Reference.html 48 | */ 49 | 50 | /** 51 | * The title attributes dictionary used for tab bar item's unselected state. 52 | */ 53 | @property (copy) NSDictionary *unselectedTitleAttributes; 54 | 55 | /** 56 | * The title attributes dictionary used for tab bar item's selected state. 57 | */ 58 | @property (copy) NSDictionary *selectedTitleAttributes; 59 | 60 | #pragma mark - Image configuration 61 | 62 | /** 63 | * The offset for the rectangle around the tab bar item's image. 64 | */ 65 | @property (nonatomic) UIOffset imagePositionAdjustment; 66 | 67 | /** 68 | * The image used for tab bar item's selected state. 69 | */ 70 | - (UIImage *)finishedSelectedImage; 71 | 72 | /** 73 | * The image used for tab bar item's unselected state. 74 | */ 75 | - (UIImage *)finishedUnselectedImage; 76 | 77 | /** 78 | * Sets the tab bar item's selected and unselected images. 79 | */ 80 | - (void)setFinishedSelectedImage:(UIImage *)selectedImage withFinishedUnselectedImage:(UIImage *)unselectedImage; 81 | 82 | #pragma mark - Background configuration 83 | 84 | /** 85 | * The background image used for tab bar item's selected state. 86 | */ 87 | - (UIImage *)backgroundSelectedImage; 88 | 89 | /** 90 | * The background image used for tab bar item's unselected state. 91 | */ 92 | - (UIImage *)backgroundUnselectedImage; 93 | 94 | /** 95 | * Sets the tab bar item's selected and unselected background images. 96 | */ 97 | - (void)setBackgroundSelectedImage:(UIImage *)selectedImage withUnselectedImage:(UIImage *)unselectedImage; 98 | 99 | #pragma mark - Badge configuration 100 | 101 | /** 102 | * Text that is displayed in the upper-right corner of the item with a surrounding background. 103 | */ 104 | @property (nonatomic, copy) NSString *badgeValue; 105 | 106 | /** 107 | * Image used for background of badge. 108 | */ 109 | @property (strong) UIImage *badgeBackgroundImage; 110 | 111 | /** 112 | * Color used for badge's background. 113 | */ 114 | @property (strong) UIColor *badgeBackgroundColor; 115 | 116 | /** 117 | * Color used for badge's text. 118 | */ 119 | @property (strong) UIColor *badgeTextColor; 120 | 121 | /** 122 | * The offset for the rectangle around the tab bar item's badge. 123 | */ 124 | @property (nonatomic) UIOffset badgePositionAdjustment; 125 | 126 | /** 127 | * Font used for badge's text. 128 | */ 129 | @property (nonatomic) UIFont *badgeTextFont; 130 | 131 | @end 132 | -------------------------------------------------------------------------------- /RDVTabBarController/RDVTabBarItem.m: -------------------------------------------------------------------------------- 1 | // RDVTabBarItem.h 2 | // RDVTabBarController 3 | // 4 | // Copyright (c) 2013 Robert Dimitrov 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #import "RDVTabBarItem.h" 25 | 26 | @interface RDVTabBarItem () { 27 | NSString *_title; 28 | UIOffset _imagePositionAdjustment; 29 | NSDictionary *_unselectedTitleAttributes; 30 | NSDictionary *_selectedTitleAttributes; 31 | } 32 | 33 | @property UIImage *unselectedBackgroundImage; 34 | @property UIImage *selectedBackgroundImage; 35 | @property UIImage *unselectedImage; 36 | @property UIImage *selectedImage; 37 | 38 | @end 39 | 40 | @implementation RDVTabBarItem 41 | 42 | - (id)initWithFrame:(CGRect)frame { 43 | self = [super initWithFrame:frame]; 44 | if (self) { 45 | [self commonInitialization]; 46 | } 47 | return self; 48 | } 49 | 50 | - (id)initWithCoder:(NSCoder *)aDecoder { 51 | self = [super initWithCoder:aDecoder]; 52 | if (self) { 53 | [self commonInitialization]; 54 | } 55 | return self; 56 | } 57 | 58 | - (id)init { 59 | return [self initWithFrame:CGRectZero]; 60 | } 61 | 62 | - (void)commonInitialization { 63 | // Setup defaults 64 | 65 | [self setBackgroundColor:[UIColor clearColor]]; 66 | 67 | _title = @""; 68 | _titlePositionAdjustment = UIOffsetZero; 69 | 70 | if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) { 71 | _unselectedTitleAttributes = @{ 72 | NSFontAttributeName: [UIFont systemFontOfSize:12], 73 | NSForegroundColorAttributeName: [UIColor blackColor], 74 | }; 75 | } else { 76 | #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_7_0 77 | _unselectedTitleAttributes = @{ 78 | UITextAttributeFont: [UIFont systemFontOfSize:12], 79 | UITextAttributeTextColor: [UIColor blackColor], 80 | }; 81 | #endif 82 | } 83 | 84 | _selectedTitleAttributes = [_unselectedTitleAttributes copy]; 85 | _badgeBackgroundColor = [UIColor redColor]; 86 | _badgeTextColor = [UIColor whiteColor]; 87 | _badgeTextFont = [UIFont systemFontOfSize:12]; 88 | _badgePositionAdjustment = UIOffsetZero; 89 | } 90 | 91 | - (void)drawRect:(CGRect)rect { 92 | CGSize frameSize = self.frame.size; 93 | CGSize imageSize = CGSizeZero; 94 | CGSize titleSize = CGSizeZero; 95 | NSDictionary *titleAttributes = nil; 96 | UIImage *backgroundImage = nil; 97 | UIImage *image = nil; 98 | CGFloat imageStartingY = 0.0f; 99 | 100 | if ([self isSelected]) { 101 | image = [self selectedImage]; 102 | backgroundImage = [self selectedBackgroundImage]; 103 | titleAttributes = [self selectedTitleAttributes]; 104 | 105 | if (!titleAttributes) { 106 | titleAttributes = [self unselectedTitleAttributes]; 107 | } 108 | } else { 109 | image = [self unselectedImage]; 110 | backgroundImage = [self unselectedBackgroundImage]; 111 | titleAttributes = [self unselectedTitleAttributes]; 112 | } 113 | 114 | imageSize = [image size]; 115 | 116 | CGContextRef context = UIGraphicsGetCurrentContext(); 117 | CGContextSaveGState(context); 118 | 119 | [backgroundImage drawInRect:self.bounds]; 120 | 121 | // Draw image and title 122 | 123 | if (![_title length]) { 124 | [image drawInRect:CGRectMake(roundf(frameSize.width / 2 - imageSize.width / 2) + 125 | _imagePositionAdjustment.horizontal, 126 | roundf(frameSize.height / 2 - imageSize.height / 2) + 127 | _imagePositionAdjustment.vertical, 128 | imageSize.width, imageSize.height)]; 129 | } else { 130 | titleSize = [_title boundingRectWithSize:CGSizeMake(frameSize.width, 20) 131 | options:NSStringDrawingUsesLineFragmentOrigin 132 | attributes:titleAttributes 133 | context:nil].size; 134 | 135 | imageStartingY = roundf((frameSize.height - imageSize.height - titleSize.height) / 2); 136 | 137 | [image drawInRect:CGRectMake(roundf(frameSize.width / 2 - imageSize.width / 2) + 138 | _imagePositionAdjustment.horizontal, 139 | imageStartingY + _imagePositionAdjustment.vertical, 140 | imageSize.width, imageSize.height)]; 141 | 142 | CGContextSetFillColorWithColor(context, [titleAttributes[NSForegroundColorAttributeName] CGColor]); 143 | 144 | [_title drawInRect:CGRectMake(roundf(frameSize.width / 2 - titleSize.width / 2) + 145 | _titlePositionAdjustment.horizontal, 146 | imageStartingY + imageSize.height + _titlePositionAdjustment.vertical, 147 | titleSize.width, titleSize.height) 148 | withAttributes:titleAttributes]; 149 | } 150 | 151 | // Draw badges 152 | 153 | if ([[self badgeValue] integerValue] != 0) { 154 | CGSize badgeSize = CGSizeZero; 155 | 156 | if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) { 157 | badgeSize = [_badgeValue boundingRectWithSize:CGSizeMake(frameSize.width, 20) 158 | options:NSStringDrawingUsesLineFragmentOrigin 159 | attributes:@{NSFontAttributeName: [self badgeTextFont]} 160 | context:nil].size; 161 | } else { 162 | #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_7_0 163 | badgeSize = [_badgeValue sizeWithFont:[self badgeTextFont] 164 | constrainedToSize:CGSizeMake(frameSize.width, 20)]; 165 | #endif 166 | } 167 | 168 | CGFloat textOffset = 2.0f; 169 | 170 | if (badgeSize.width < badgeSize.height) { 171 | badgeSize = CGSizeMake(badgeSize.height, badgeSize.height); 172 | } 173 | 174 | CGRect badgeBackgroundFrame = CGRectMake(roundf(frameSize.width / 2 + (image.size.width / 2) * 0.9) + 175 | [self badgePositionAdjustment].horizontal, 176 | textOffset + [self badgePositionAdjustment].vertical, 177 | badgeSize.width + 2 * textOffset, badgeSize.height + 2 * textOffset); 178 | 179 | if ([self badgeBackgroundColor]) { 180 | CGContextSetFillColorWithColor(context, [[self badgeBackgroundColor] CGColor]); 181 | 182 | CGContextFillEllipseInRect(context, badgeBackgroundFrame); 183 | } else if ([self badgeBackgroundImage]) { 184 | [[self badgeBackgroundImage] drawInRect:badgeBackgroundFrame]; 185 | } 186 | 187 | CGContextSetFillColorWithColor(context, [[self badgeTextColor] CGColor]); 188 | 189 | if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) { 190 | NSMutableParagraphStyle *badgeTextStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy]; 191 | [badgeTextStyle setLineBreakMode:NSLineBreakByWordWrapping]; 192 | [badgeTextStyle setAlignment:NSTextAlignmentCenter]; 193 | 194 | NSDictionary *badgeTextAttributes = @{ 195 | NSFontAttributeName: [self badgeTextFont], 196 | NSForegroundColorAttributeName: [self badgeTextColor], 197 | NSParagraphStyleAttributeName: badgeTextStyle, 198 | }; 199 | 200 | [[self badgeValue] drawInRect:CGRectMake(CGRectGetMinX(badgeBackgroundFrame) + textOffset, 201 | CGRectGetMinY(badgeBackgroundFrame) + textOffset, 202 | badgeSize.width, badgeSize.height) 203 | withAttributes:badgeTextAttributes]; 204 | } else { 205 | #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_7_0 206 | [[self badgeValue] drawInRect:CGRectMake(CGRectGetMinX(badgeBackgroundFrame) + textOffset, 207 | CGRectGetMinY(badgeBackgroundFrame) + textOffset, 208 | badgeSize.width, badgeSize.height) 209 | withFont:[self badgeTextFont] 210 | lineBreakMode:NSLineBreakByTruncatingTail 211 | alignment:NSTextAlignmentCenter]; 212 | #endif 213 | } 214 | } 215 | 216 | CGContextRestoreGState(context); 217 | } 218 | 219 | #pragma mark - Image configuration 220 | 221 | - (UIImage *)finishedSelectedImage { 222 | return [self selectedImage]; 223 | } 224 | 225 | - (UIImage *)finishedUnselectedImage { 226 | return [self unselectedImage]; 227 | } 228 | 229 | - (void)setFinishedSelectedImage:(UIImage *)selectedImage withFinishedUnselectedImage:(UIImage *)unselectedImage { 230 | if (selectedImage && (selectedImage != [self selectedImage])) { 231 | [self setSelectedImage:selectedImage]; 232 | } 233 | 234 | if (unselectedImage && (unselectedImage != [self unselectedImage])) { 235 | [self setUnselectedImage:unselectedImage]; 236 | } 237 | } 238 | 239 | - (void)setBadgeValue:(NSString *)badgeValue { 240 | _badgeValue = badgeValue; 241 | 242 | [self setNeedsDisplay]; 243 | } 244 | 245 | #pragma mark - Background configuration 246 | 247 | - (UIImage *)backgroundSelectedImage { 248 | return [self selectedBackgroundImage]; 249 | } 250 | 251 | - (UIImage *)backgroundUnselectedImage { 252 | return [self unselectedBackgroundImage]; 253 | } 254 | 255 | - (void)setBackgroundSelectedImage:(UIImage *)selectedImage withUnselectedImage:(UIImage *)unselectedImage { 256 | if (selectedImage && (selectedImage != [self selectedBackgroundImage])) { 257 | [self setSelectedBackgroundImage:selectedImage]; 258 | } 259 | 260 | if (unselectedImage && (unselectedImage != [self unselectedBackgroundImage])) { 261 | [self setUnselectedBackgroundImage:unselectedImage]; 262 | } 263 | } 264 | 265 | #pragma mark - Accessibility 266 | 267 | - (NSString *)accessibilityLabel{ 268 | return @"tabbarItem"; 269 | } 270 | 271 | - (BOOL)isAccessibilityElement 272 | { 273 | return YES; 274 | } 275 | 276 | 277 | @end 278 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RDVTabBarController 2 | 3 | [![iPad screenshot](Screenshots/iPad-small.png)](Screenshots/iPad.png) 4 | 5 | [![iPhone screenshot](Screenshots/iPhone-small.png)](Screenshots/iPhone.png) 6 | 7 | * Supports iPad and iPhone 8 | * Supports landscape and portrait orientations 9 | * Can be used inside UINavigationController 10 | * Customizable badges 11 | 12 | ## Installation 13 | 14 | ### CocoaPods 15 | 16 | If you're using [CocoaPods](http://www.cocoapods.org), simply add `pod 'RDVTabBarController'` to your Podfile. 17 | 18 | ### Drag & Drop 19 | 20 | Add the items from `RDVTabBarController` directory to your project. If you don't have ARC enabled, you will need to set a `-fobjc-arc` compiler flag on the `.m` source files. 21 | 22 | ## Example Usage 23 | 24 | #### Initialize RDVTabBarController 25 | 26 | The initialization is similar to the one for `UITabBarController`. Create an instance of the `tabBarController` and initialize its `viewControllers`. 27 | 28 | ```objective-c 29 | UIViewController *firstViewController = [[RDVFirstViewController alloc] init]; 30 | UIViewController *firstNavigationController = [[UINavigationController alloc] 31 | initWithRootViewController:firstViewController]; 32 | 33 | UIViewController *secondViewController = [[RDVSecondViewController alloc] init]; 34 | UIViewController *secondNavigationController = [[UINavigationController alloc] 35 | initWithRootViewController:secondViewController]; 36 | 37 | UIViewController *thirdViewController = [[RDVThirdViewController alloc] init]; 38 | UIViewController *thirdNavigationController = [[UINavigationController alloc] 39 | initWithRootViewController:thirdViewController]; 40 | 41 | RDVTabBarController *tabBarController = [[RDVTabBarController alloc] init]; 42 | [tabBarController setViewControllers:@[firstNavigationController, secondNavigationController, 43 | thirdNavigationController]]; 44 | self.viewController = tabBarController; 45 | ``` 46 | 47 | #### Customize RDVTabBarController 48 | Each `RDVTabBarItem` has `selectedBackground`, `unselectedBackground` and corresponding properties for the icons: `selectedImage` and `unselectedImage`. 49 | 50 | ```objective-c 51 | UIImage *finishedImage = [UIImage imageNamed:@"tabbar_selected_background"]; 52 | UIImage *unfinishedImage = [UIImage imageNamed:@"tabbar_normal_background"]; 53 | NSArray *tabBarItemImages = @[@"first", @"second", @"third"]; 54 | 55 | RDVTabBar *tabBar = [tabBarController tabBar]; 56 | 57 | [tabBar setFrame:CGRectMake(CGRectGetMinX(tabBar.frame), CGRectGetMinY(tabBar.frame), CGRectGetWidth(tabBar.frame), 63)]; 58 | 59 | NSInteger index = 0; 60 | for (RDVTabBarItem *item in [[tabBarController tabBar] items]) { 61 | [item setBackgroundSelectedImage:finishedImage withUnselectedImage:unfinishedImage]; 62 | UIImage *selectedimage = [UIImage imageNamed:[NSString stringWithFormat:@"%@_selected", 63 | [tabBarItemImages objectAtIndex:index]]]; 64 | UIImage *unselectedimage = [UIImage imageNamed:[NSString stringWithFormat:@"%@_normal", 65 | [tabBarItemImages objectAtIndex:index]]]; 66 | [item setFinishedSelectedImage:selectedimage withFinishedUnselectedImage:unselectedimage]; 67 | 68 | index++; 69 | } 70 | ``` 71 | 72 | #### Make the tab bar translucent 73 | 74 | `RDVTabBar` has `translucent` property which determines how it is going to be handled. 75 | 76 | ```objective-c 77 | RDVTabBar *tabBar = tabBarController.tabBar; 78 | 79 | // After the tabBarController initialization 80 | tabBar.translucent = YES; 81 | 82 | // Customize the tabBar background 83 | tabBar.backgroundView.backgroundColor = [UIColor colorWithRed:245/255.0 84 | green:245/255.0 85 | blue:245/255.0 86 | alpha:0.9]; 87 | 88 | // Inside the tabbed viewControllers 89 | - (void)viewDidLoad { 90 | [super viewDidLoad]; 91 | 92 | ... 93 | 94 | if (self.rdv_tabBarController.tabBar.translucent) { 95 | CGFloat tabBarHeight = CGRectGetHeight(self.rdv_tabBarController.tabBar.frame); 96 | UIEdgeInsets insets = UIEdgeInsetsMake(0, 0, tabBarHeight, 0); 97 | 98 | self.tableView.contentInset = insets; 99 | self.tableView.scrollIndicatorInsets = insets; 100 | } 101 | } 102 | 103 | ``` 104 | 105 | ## Requirements 106 | 107 | * ARC 108 | * iOS 8.0 or later 109 | * Xcode 11 110 | 111 | ## Contact 112 | 113 | [Robert Dimitrov](http://robbdimitrov.com) 114 | [@robbdimitrov](https://twitter.com/robbdimitrov) 115 | 116 | ## License 117 | 118 | RDVTabBarController is available under the MIT license. See the LICENSE file for more info. 119 | -------------------------------------------------------------------------------- /Screenshots/iPad-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Screenshots/iPad-small.png -------------------------------------------------------------------------------- /Screenshots/iPad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Screenshots/iPad.png -------------------------------------------------------------------------------- /Screenshots/iPhone-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Screenshots/iPhone-small.png -------------------------------------------------------------------------------- /Screenshots/iPhone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robbdimitrov/RDVTabBarController/074c2059c1d360272ae188dc9c3cf50a9ca3f8a3/Screenshots/iPhone.png --------------------------------------------------------------------------------