├── RSCustomTabbarController ├── Assets.xcassets │ ├── Contents.json │ ├── images │ │ ├── Contents.json │ │ ├── tabbar3normal.imageset │ │ │ ├── Lion.png │ │ │ ├── Lion-1.png │ │ │ └── Contents.json │ │ ├── tabbar0normal.imageset │ │ │ ├── Pacman.png │ │ │ ├── Pacman-1.png │ │ │ └── Contents.json │ │ ├── browser_tab_normal.imageset │ │ │ ├── 200X250.png │ │ │ ├── 400X500.png │ │ │ └── Contents.json │ │ ├── tabbar1normal.imageset │ │ │ ├── Super Mario.png │ │ │ ├── Super Mario-1.png │ │ │ └── Contents.json │ │ ├── tabbar2normal.imageset │ │ │ ├── US Airborne.png │ │ │ ├── US Airborne-1.png │ │ │ └── Contents.json │ │ ├── tabbar0selected.imageset │ │ │ ├── Pacman Filled.png │ │ │ ├── Pacman Filled-1.png │ │ │ └── Contents.json │ │ ├── tabbar3selected.imageset │ │ │ ├── Lion Filled-1.png │ │ │ ├── Lion Filled.png │ │ │ └── Contents.json │ │ ├── browser_tab_selected.imageset │ │ │ ├── 200X250 copy.png │ │ │ ├── 400X500 copy.png │ │ │ └── Contents.json │ │ ├── tabbar1selected.imageset │ │ │ ├── Super Mario Filled.png │ │ │ ├── Super Mario Filled-1.png │ │ │ └── Contents.json │ │ ├── tabbar2selected.imageset │ │ │ ├── US Airborne Filled.png │ │ │ ├── US Airborne Filled-1.png │ │ │ └── Contents.json │ │ ├── add_browser_tab_normal.imageset │ │ │ ├── plus_132X80_normal.png │ │ │ ├── plus_66X40_normal.png │ │ │ └── Contents.json │ │ └── add_browser_tab_pressed.imageset │ │ │ ├── plus_132X80_pressed.png │ │ │ ├── plus_66X40_pressed.png │ │ │ └── Contents.json │ └── AppIcon.appiconset │ │ └── Contents.json ├── common │ ├── ChildVC.h │ ├── BrowserChildVC.h │ ├── ChildVC.m │ └── BrowserChildVC.m ├── Demo5 │ ├── RSCustomTabbarController-Bridging-Header.h │ ├── SwiftChildVC.swift │ └── Demo5TabbarController.swift ├── MenuTableViewController.h ├── main.m ├── Demo Transition Animation │ ├── JumpInTabbarTransitionAnimation.h │ ├── SlidingTabbarTransitionAnimation.h │ ├── FadingTabbarTransitionAnimation.h │ ├── SlidingTabbarTransitionAnimation.m │ ├── JumpInTabbarTransitionAnimation.m │ ├── FadingTabbarTransitionAnimation.m │ └── PopupTabbarTransitionAnimation.swift ├── Demo3 │ ├── Demo3TabbarController.h │ └── Demo3TabbarController.m ├── Demo6 │ ├── Demo6TabbarItemCell.h │ ├── Demo6TabbarItemCell.m │ ├── Demo6TabbarControllerViewController.h │ └── demo6.storyboard ├── MenuTableCell.h ├── Demo4 │ ├── Demo4TabbarController.h │ ├── Demo4TabbarCell.h │ ├── Demo4TabbarCell.m │ └── Demo4TabbarController.m ├── Demo2 │ ├── Demo2TabbarController.h │ └── Demo2TabbarController.m ├── Info.plist ├── Demo1 │ ├── Demo1TabbarController.h │ ├── Demo1TabbarController.m │ └── demo1.storyboard ├── MenuTableCell.m ├── CustomTabbarConroller │ ├── RSCustomTabbarController.h │ ├── RSCustomTabbarImplementationDelegate.h │ ├── RSCustomTabbarControllerLifecycleDelegte.h │ ├── RSCustomTabbarTransitionAnimationDelegate.h │ ├── RSCustomTabbarControllerBasic.h │ ├── RSCustomTabbarDelegate.h │ ├── RSCustomTabbarController.m │ └── RSCustomTabbarControllerBasic.m ├── AppDelegate.h ├── MenuData.plist ├── Base.lproj │ └── LaunchScreen.storyboard ├── AppDelegate.m ├── menu.storyboard └── MenuTableViewController.m ├── LICENSE ├── .gitignore └── README.md /RSCustomTabbarController/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/tabbar3normal.imageset/Lion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSCustomTabbarController/HEAD/RSCustomTabbarController/Assets.xcassets/images/tabbar3normal.imageset/Lion.png -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/tabbar0normal.imageset/Pacman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSCustomTabbarController/HEAD/RSCustomTabbarController/Assets.xcassets/images/tabbar0normal.imageset/Pacman.png -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/tabbar3normal.imageset/Lion-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSCustomTabbarController/HEAD/RSCustomTabbarController/Assets.xcassets/images/tabbar3normal.imageset/Lion-1.png -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/tabbar0normal.imageset/Pacman-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSCustomTabbarController/HEAD/RSCustomTabbarController/Assets.xcassets/images/tabbar0normal.imageset/Pacman-1.png -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/browser_tab_normal.imageset/200X250.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSCustomTabbarController/HEAD/RSCustomTabbarController/Assets.xcassets/images/browser_tab_normal.imageset/200X250.png -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/browser_tab_normal.imageset/400X500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSCustomTabbarController/HEAD/RSCustomTabbarController/Assets.xcassets/images/browser_tab_normal.imageset/400X500.png -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/tabbar1normal.imageset/Super Mario.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSCustomTabbarController/HEAD/RSCustomTabbarController/Assets.xcassets/images/tabbar1normal.imageset/Super Mario.png -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/tabbar2normal.imageset/US Airborne.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSCustomTabbarController/HEAD/RSCustomTabbarController/Assets.xcassets/images/tabbar2normal.imageset/US Airborne.png -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/tabbar0selected.imageset/Pacman Filled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSCustomTabbarController/HEAD/RSCustomTabbarController/Assets.xcassets/images/tabbar0selected.imageset/Pacman Filled.png -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/tabbar1normal.imageset/Super Mario-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSCustomTabbarController/HEAD/RSCustomTabbarController/Assets.xcassets/images/tabbar1normal.imageset/Super Mario-1.png -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/tabbar2normal.imageset/US Airborne-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSCustomTabbarController/HEAD/RSCustomTabbarController/Assets.xcassets/images/tabbar2normal.imageset/US Airborne-1.png -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/tabbar3selected.imageset/Lion Filled-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSCustomTabbarController/HEAD/RSCustomTabbarController/Assets.xcassets/images/tabbar3selected.imageset/Lion Filled-1.png -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/tabbar3selected.imageset/Lion Filled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSCustomTabbarController/HEAD/RSCustomTabbarController/Assets.xcassets/images/tabbar3selected.imageset/Lion Filled.png -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/tabbar0selected.imageset/Pacman Filled-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSCustomTabbarController/HEAD/RSCustomTabbarController/Assets.xcassets/images/tabbar0selected.imageset/Pacman Filled-1.png -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/browser_tab_selected.imageset/200X250 copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSCustomTabbarController/HEAD/RSCustomTabbarController/Assets.xcassets/images/browser_tab_selected.imageset/200X250 copy.png -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/browser_tab_selected.imageset/400X500 copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSCustomTabbarController/HEAD/RSCustomTabbarController/Assets.xcassets/images/browser_tab_selected.imageset/400X500 copy.png -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/tabbar1selected.imageset/Super Mario Filled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSCustomTabbarController/HEAD/RSCustomTabbarController/Assets.xcassets/images/tabbar1selected.imageset/Super Mario Filled.png -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/tabbar2selected.imageset/US Airborne Filled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSCustomTabbarController/HEAD/RSCustomTabbarController/Assets.xcassets/images/tabbar2selected.imageset/US Airborne Filled.png -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/tabbar1selected.imageset/Super Mario Filled-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSCustomTabbarController/HEAD/RSCustomTabbarController/Assets.xcassets/images/tabbar1selected.imageset/Super Mario Filled-1.png -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/tabbar2selected.imageset/US Airborne Filled-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSCustomTabbarController/HEAD/RSCustomTabbarController/Assets.xcassets/images/tabbar2selected.imageset/US Airborne Filled-1.png -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/add_browser_tab_normal.imageset/plus_132X80_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSCustomTabbarController/HEAD/RSCustomTabbarController/Assets.xcassets/images/add_browser_tab_normal.imageset/plus_132X80_normal.png -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/add_browser_tab_normal.imageset/plus_66X40_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSCustomTabbarController/HEAD/RSCustomTabbarController/Assets.xcassets/images/add_browser_tab_normal.imageset/plus_66X40_normal.png -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/add_browser_tab_pressed.imageset/plus_132X80_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSCustomTabbarController/HEAD/RSCustomTabbarController/Assets.xcassets/images/add_browser_tab_pressed.imageset/plus_132X80_pressed.png -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/add_browser_tab_pressed.imageset/plus_66X40_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSCustomTabbarController/HEAD/RSCustomTabbarController/Assets.xcassets/images/add_browser_tab_pressed.imageset/plus_66X40_pressed.png -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/tabbar0normal.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Pacman.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Pacman-1.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/tabbar3normal.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Lion.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Lion-1.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/browser_tab_normal.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "200X250.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "400X500.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/tabbar1normal.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Super Mario.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Super Mario-1.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/tabbar2normal.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "US Airborne.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "US Airborne-1.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/tabbar3selected.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Lion Filled.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Lion Filled-1.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/browser_tab_selected.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "200X250 copy.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "400X500 copy.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/tabbar0selected.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Pacman Filled.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Pacman Filled-1.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/add_browser_tab_normal.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "plus_66X40_normal.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "plus_132X80_normal.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/tabbar1selected.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Super Mario Filled.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Super Mario Filled-1.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/tabbar2selected.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "US Airborne Filled.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "US Airborne Filled-1.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/images/add_browser_tab_pressed.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "plus_66X40_pressed.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "plus_132X80_pressed.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Ratul sharker 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /RSCustomTabbarController/common/ChildVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // ChildVC.h 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 8/30/16. 6 | // Copyright © 2016 funtoos. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | 25 | @interface ChildVC : UIViewController 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Demo5/RSCustomTabbarController-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 7 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all copies or substantial 12 | // portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 15 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 16 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 18 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | #import "RSCustomTabbarController.h" 21 | #import "AppDelegate.h" 22 | #import "RSCustomTabbarTransitionAnimationDelegate.h" 23 | -------------------------------------------------------------------------------- /RSCustomTabbarController/common/BrowserChildVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // BrowserChildVC.h 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 10/8/16. 6 | // Copyright © 2016 funtoos. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | 25 | @interface BrowserChildVC : UIViewController 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /RSCustomTabbarController/MenuTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // MenuViewController.h 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 9/2/16. 6 | // Copyright © 2016 funtoos. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | #import "RSCustomTabbarController.h" 25 | 26 | @interface MenuTableViewController : UITableViewController 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /RSCustomTabbarController/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 8/29/16. 6 | // Copyright © 2016 funtoos. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | #import "AppDelegate.h" 25 | 26 | int main(int argc, char * argv[]) { 27 | @autoreleasepool { 28 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Demo Transition Animation/JumpInTabbarTransitionAnimation.h: -------------------------------------------------------------------------------- 1 | // 2 | // JumpInTabbarTransitionAnimation.h 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 9/27/16. 6 | // Copyright © 2016 funtoos. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "RSCustomTabbarTransitionAnimationDelegate.h" 24 | 25 | @interface JumpInTabbarTransitionAnimation : NSObject 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Demo Transition Animation/SlidingTabbarTransitionAnimation.h: -------------------------------------------------------------------------------- 1 | // 2 | // SlidingTabbarTransitionAnimation.h 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 9/26/16. 6 | // Copyright © 2016 funtoos. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "RSCustomTabbarTransitionAnimationDelegate.h" 24 | 25 | @interface SlidingTabbarTransitionAnimation : NSObject 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "83.5x83.5", 66 | "scale" : "2x" 67 | } 68 | ], 69 | "info" : { 70 | "version" : 1, 71 | "author" : "xcode" 72 | } 73 | } -------------------------------------------------------------------------------- /RSCustomTabbarController/Demo3/Demo3TabbarController.h: -------------------------------------------------------------------------------- 1 | // 2 | // Demo3TabbarController.h 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 9/10/16. 6 | // Copyright © 2016 funtoos. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "RSCustomTabbarController.h" 24 | 25 | @interface Demo3TabbarController : RSCustomTabbarController 26 | 27 | @property IBOutlet UIView *viewControllerContainer; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Demo Transition Animation/FadingTabbarTransitionAnimation.h: -------------------------------------------------------------------------------- 1 | // 2 | // FadingTabbarTransitionAnimation.h 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 9/23/16. 6 | // Copyright © 2016 funtoos. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "RSCustomTabbarTransitionAnimationDelegate.h" 24 | 25 | 26 | @interface FadingTabbarTransitionAnimation : NSObject 27 | 28 | 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xcuserstate 23 | 24 | ## Obj-C/Swift specific 25 | *.hmap 26 | *.ipa 27 | *.dSYM.zip 28 | *.dSYM 29 | 30 | # CocoaPods 31 | # 32 | # We recommend against adding the Pods directory to your .gitignore. However 33 | # you should judge for yourself, the pros and cons are mentioned at: 34 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 35 | # 36 | # Pods/ 37 | 38 | # Carthage 39 | # 40 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 41 | # Carthage/Checkouts 42 | 43 | Carthage/Build 44 | 45 | # fastlane 46 | # 47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 48 | # screenshots whenever they are needed. 49 | # For more information about the recommended setup visit: 50 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 51 | 52 | fastlane/report.xml 53 | fastlane/screenshots 54 | 55 | #Code Injection 56 | # 57 | # After new code Injection tools there's a generated folder /iOSInjectionProject 58 | # https://github.com/johnno1962/injectionforxcode 59 | 60 | iOSInjectionProject/ 61 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Demo6/Demo6TabbarItemCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // Demo6TabbarItemCell.h 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 1/31/17. 6 | // Copyright © 2017 funtoos. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | 25 | #define DEMO6_TABBAR_ITEM_CELL_REUSING_ID @"demo6tabbaritemcell" 26 | 27 | @interface Demo6TabbarItemCell : UICollectionViewCell 28 | 29 | @property (strong, nonatomic) IBOutlet UILabel *mViewTabbarItemLabel; 30 | 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /RSCustomTabbarController/MenuTableCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // MenuTableCell.h 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 9/2/16. 6 | // Copyright © 2016 funtoos. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | 25 | @interface MenuTableCell : UITableViewCell 26 | 27 | 28 | @property (strong, nonatomic) IBOutlet UILabel *titleLabel; 29 | @property (strong, nonatomic) IBOutlet UILabel *descriptionLabel; 30 | @property (strong, nonatomic) IBOutlet UIStepper *initialViewControllerSelectorStepper; 31 | @property (strong, nonatomic) IBOutlet UILabel *stepperStatusLabel; 32 | 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Demo4/Demo4TabbarController.h: -------------------------------------------------------------------------------- 1 | // 2 | // Demo4TabbarController.h 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 10/8/16. 6 | // Copyright © 2016 funtoos. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "RSCustomTabbarController.h" 24 | 25 | 26 | 27 | 28 | 29 | 30 | @interface Demo4TabbarController : RSCustomTabbarController 31 | 32 | @property IBOutlet UIView *viewControllerContainer; 33 | 34 | @property IBOutletCollection(NSLayoutConstraint) NSArray *tabbarContainerHeight; 35 | @property IBOutletCollection(NSLayoutConstraint) NSArray *tabbarWidgetHolderTop; 36 | 37 | 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Demo2/Demo2TabbarController.h: -------------------------------------------------------------------------------- 1 | // 2 | // Demo2TabbarController.h 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 8/31/16. 6 | // Copyright © 2016 funtoos. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "RSCustomTabbarController.h" 24 | 25 | @interface Demo2TabbarController : RSCustomTabbarController 26 | 27 | 28 | #pragma mark CustomTabbarImplementationDelegate 29 | @property IBOutlet UIView *viewControllerContainer; 30 | @property IBOutletCollection (NSLayoutConstraint) NSArray *tabbarContainerHeight; 31 | @property IBOutletCollection(NSLayoutConstraint) NSArray *tabbarWidgetHolderTop; 32 | 33 | 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | menu 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UIRequiresFullScreen 34 | 35 | UIStatusBarHidden 36 | 37 | UISupportedInterfaceOrientations 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationLandscapeLeft 41 | UIInterfaceOrientationLandscapeRight 42 | 43 | UISupportedInterfaceOrientations~ipad 44 | 45 | UIInterfaceOrientationPortrait 46 | UIInterfaceOrientationPortraitUpsideDown 47 | UIInterfaceOrientationLandscapeLeft 48 | UIInterfaceOrientationLandscapeRight 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Demo1/Demo1TabbarController.h: -------------------------------------------------------------------------------- 1 | // 2 | // Demo1TabbarController.h 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 8/29/16. 6 | // Copyright © 2016 funtoos. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | #import "RSCustomTabbarController.h" 25 | 26 | 27 | @interface Demo1TabbarController : RSCustomTabbarController 28 | 29 | 30 | #pragma mark implementation properties 31 | @property IBOutlet UIView *viewControllerContainer; 32 | @property IBOutletCollection (NSLayoutConstraint) NSArray *tabbarContainerHeight; 33 | @property IBOutletCollection (NSLayoutConstraint) NSArray *tabbarWidgetHolderTop; 34 | 35 | 36 | 37 | @end 38 | 39 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Demo4/Demo4TabbarCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // Demo4TabbarCell.h 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 10/8/16. 6 | // Copyright © 2016 funtoos. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | #import 23 | 24 | @class Demo4TabbarCell; 25 | 26 | @protocol Demo4TabbarCellDelegate 27 | 28 | -(void)crossPressedForDemo4TabbarCell:(Demo4TabbarCell*)cell; 29 | 30 | @end 31 | 32 | 33 | @interface Demo4TabbarCell : UICollectionViewCell 34 | 35 | @property IBOutlet UIImageView *mViewImageView; 36 | @property IBOutlet UILabel *mViewLabel; 37 | @property id delegate; 38 | 39 | 40 | -(void)setNormalOrSelectedImage:(BOOL)isNormal; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Demo5/SwiftChildVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftChildVC.swift 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 10/23/16. 6 | // Copyright © 2016 funtoos. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | import Foundation 24 | 25 | class SwiftChildVC : UIViewController 26 | { 27 | // 28 | // MARK: ui components 29 | // 30 | @IBOutlet var mViewLabel: UILabel! 31 | 32 | 33 | // 34 | // MARK: Life cycle Method 35 | // 36 | override func viewDidLoad() { 37 | super.viewDidLoad(); 38 | } 39 | 40 | 41 | @IBAction func backToDemoList(_ sender : UIButton) 42 | { 43 | AppDelegate.moveToMenuTableViewController(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Demo6/Demo6TabbarItemCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // Demo6TabbarItemCell.m 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 1/31/17. 6 | // Copyright © 2017 funtoos. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "Demo6TabbarItemCell.h" 24 | 25 | @implementation Demo6TabbarItemCell 26 | 27 | 28 | -(void)setSelected:(BOOL)selected 29 | { 30 | if(selected) 31 | { 32 | self.mViewTabbarItemLabel.textColor = [UIColor whiteColor]; 33 | self.mViewTabbarItemLabel.font = [UIFont systemFontOfSize:20.0]; 34 | } 35 | else 36 | { 37 | self.mViewTabbarItemLabel.textColor = [UIColor darkGrayColor]; 38 | self.mViewTabbarItemLabel.font = [UIFont systemFontOfSize:15.0]; 39 | } 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /RSCustomTabbarController/MenuTableCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // MenuTableCell.m 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 9/2/16. 6 | // Copyright © 2016 funtoos. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "MenuTableCell.h" 24 | 25 | @implementation MenuTableCell 26 | 27 | - (void)awakeFromNib { 28 | [super awakeFromNib]; 29 | // Initialization code 30 | } 31 | 32 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 33 | [super setSelected:selected animated:animated]; 34 | 35 | // Configure the view for the selected state 36 | } 37 | 38 | #pragma mark IBAction 39 | - (IBAction)onStepperValueChanged:(UIStepper*)sender 40 | { 41 | self.stepperStatusLabel.text = [NSString stringWithFormat:@"initial vc %d/%d", (int)sender.value, (int)sender.maximumValue]; 42 | } 43 | 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /RSCustomTabbarController/CustomTabbarConroller/RSCustomTabbarController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RSCustomTabbarController.h 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 8/29/16. 6 | // Copyright © 2016 funtoos. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | #import "RSCustomTabbarControllerBasic.h" 25 | 26 | // 27 | // 28 | // 29 | typedef void (^RSCustomTabbarPendingBlock)(); 30 | 31 | 32 | @interface RSCustomTabbarController : RSCustomTabbarControllerBasic 33 | 34 | -(void)addPendingBlockIntendedToBeExecutedAfterViewDidLoad:(RSCustomTabbarGeneralPurposeBlock)block; 35 | 36 | -(void)removeViewControllerFromContainerAtIndex:(NSUInteger)index; 37 | -(void)removeViewControllerFromContainer:(UIViewController*)viewController; 38 | -(void)removeAllViewControllerFromContainer; 39 | 40 | 41 | -(BOOL)isViewLoaded; 42 | -(CGRect)getViewControllerContainerFrame; 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /RSCustomTabbarController/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 8/29/16. 6 | // Copyright © 2016 funtoos. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | 25 | #import "RSCustomTabbarController.h" 26 | 27 | 28 | @interface AppDelegate : UIResponder 29 | 30 | @property (strong, nonatomic) UIWindow *window; 31 | 32 | 33 | // 34 | // getting the currently showing tabbar controller 35 | // 36 | -(void)setCurrentCustomTabbarController:(RSCustomTabbarController*)tabbarController; 37 | -(RSCustomTabbarController*)getCurrentCustomTabbarController; 38 | 39 | // 40 | // getting the navigation controller 41 | // 42 | -(void)setCurrentNavigationController:(UINavigationController*)navigationController; 43 | -(UINavigationController*)getCurrentNavigationController; 44 | 45 | // 46 | // moving to menu table view controller 47 | // 48 | +(void)moveToMenuTableViewController; 49 | 50 | @end 51 | 52 | -------------------------------------------------------------------------------- /RSCustomTabbarController/MenuData.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | menu.item.title 7 | Demo 1 8 | menu.item.description 9 | A simple trivial tabbar example 10 | menu.item.number.of.vc 11 | 4 12 | menu.item.selector 13 | showOnDemo1 14 | 15 | 16 | menu.item.title 17 | Demo 2 18 | menu.item.description 19 | Multiple tabbar in single tab controller 20 | menu.item.number.of.vc 21 | 4 22 | menu.item.selector 23 | showOnDemo2 24 | 25 | 26 | menu.item.title 27 | Demo 3 28 | menu.item.description 29 | Movable tabbar 30 | menu.item.number.of.vc 31 | 3 32 | menu.item.selector 33 | showOnDemo3 34 | 35 | 36 | menu.item.title 37 | Demo 4 38 | menu.item.description 39 | Browser like dynamic tabbar 40 | menu.item.number.of.vc 41 | 1 42 | menu.item.selector 43 | showOnDemo4 44 | 45 | 46 | menu.item.title 47 | Demo 5 48 | menu.item.description 49 | Working with swift 50 | menu.item.number.of.vc 51 | 4 52 | menu.item.selector 53 | showOnDemo5 54 | 55 | 56 | menu.item.title 57 | Demo 6 58 | menu.item.description 59 | Android View-Pager like Tabbar implementation 60 | menu.item.number.of.vc 61 | 4 62 | menu.item.selector 63 | showOnDemo6 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Demo6/Demo6TabbarControllerViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // Demo6TabbarControllerViewController.h 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 1/31/17. 6 | // Copyright © 2017 funtoos. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "RSCustomTabbarController.h" 24 | 25 | #define TABBAR_ITEM_TEXT_KEY @"tabbar.item.text.key" 26 | #define TABBAR_ITEM_SHOWN_AT_A_TIME 3.5 27 | 28 | #define DEMO6_SLIDING_PAN_GESTURE_LEFT_RIGHT_OFFSET 40 29 | 30 | 31 | #define TABBAR_BOTTOM_SELECTION_LAYER_HEIGHT 5 32 | #define TABBAR_BOTTOM_SELECTION_LAYER_COLOR [UIColor greenColor] 33 | 34 | 35 | @interface Demo6TabbarControllerViewController : RSCustomTabbarController 36 | 37 | 38 | #pragma mark RSCustomTabbarImplementationDelegate 39 | @property IBOutlet UIView *viewControllerContainer; 40 | 41 | @property IBOutletCollection(NSLayoutConstraint) NSArray *tabbarContainerHeight; 42 | @property IBOutletCollection(NSLayoutConstraint)NSArray *tabbarWidgetHolderTop; 43 | 44 | 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /RSCustomTabbarController/CustomTabbarConroller/RSCustomTabbarImplementationDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // RSCustomTabbarImplementationDelegate.h 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 10/2/16. 6 | // Copyright © 2016 funtoos. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | 24 | #ifndef RSCustomTabbarImplementationDelegate_h 25 | #define RSCustomTabbarImplementationDelegate_h 26 | 27 | // 28 | // Forward declaration of the class, 29 | // to be used in the delegate method 30 | // param 31 | // 32 | @class RSCustomTabbarControllerBasic; 33 | 34 | 35 | @protocol RSCustomTabbarImplementationDelegate 36 | 37 | @required 38 | @property UIView *viewControllerContainer; 39 | 40 | @optional 41 | @property NSArray *tabbarContainerHeight; 42 | @property NSArray *tabbarWidgetHolderTop; 43 | -(CGFloat)heightForTabbarController:(RSCustomTabbarControllerBasic*)tabbarController; 44 | 45 | @required 46 | -(void)newSelectedTabbarIndex:(NSUInteger)newSelectedIndex whereOldIndexWas:(NSUInteger)oldSelectedIndex; 47 | 48 | @end 49 | 50 | #endif /* RSCustomTabbarImplementationDelegate_h */ 51 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Demo4/Demo4TabbarCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // Demo4TabbarCell.m 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 10/8/16. 6 | // Copyright © 2016 funtoos. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "Demo4TabbarCell.h" 24 | 25 | @implementation Demo4TabbarCell 26 | 27 | -(void)awakeFromNib 28 | { 29 | [self setNormalImage]; 30 | } 31 | 32 | #pragma mark IBActions 33 | - (IBAction)onCrossBtnPressed:(id)sender 34 | { 35 | if(self.delegate && 36 | [self.delegate respondsToSelector:@selector(crossPressedForDemo4TabbarCell:)]) 37 | { 38 | [self.delegate crossPressedForDemo4TabbarCell:self]; 39 | } 40 | else 41 | { 42 | NSLog(@"delegate for Demo4Cell is not implemented"); 43 | } 44 | } 45 | 46 | 47 | #pragma mark public method 48 | 49 | -(void)setNormalOrSelectedImage:(BOOL)isSelected 50 | { 51 | NSString *imgName; 52 | 53 | if(!isSelected) 54 | { 55 | imgName = @"browser_tab_normal"; 56 | } 57 | else 58 | { 59 | imgName = @"browser_tab_selected"; 60 | } 61 | 62 | self.mViewImageView.image = [[UIImage imageNamed:imgName] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 24, 0, 26) 63 | resizingMode:UIImageResizingModeStretch]; 64 | } 65 | -(void)setSelectedImage 66 | { 67 | 68 | } 69 | 70 | -(void)setNormalImage 71 | { 72 | 73 | } 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /RSCustomTabbarController/CustomTabbarConroller/RSCustomTabbarControllerLifecycleDelegte.h: -------------------------------------------------------------------------------- 1 | // 2 | // RSCustomTabbarLifecycleDelegte.h 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 10/26/16. 6 | // Copyright © 2016 funtoos. All rights reserved. 7 | // 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 10 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 11 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 13 | // following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all copies or substantial 16 | // portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 19 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 20 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 22 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | 25 | #ifndef RSCustomTabbarLifecycleDelegte_h 26 | #define RSCustomTabbarLifecycleDelegte_h 27 | 28 | @class RSCustomTabbarControllerBasic; 29 | 30 | @protocol RSCustomTabbarControllerLifecycleDelegte 31 | 32 | // 33 | // These method's are optional method 34 | // as the viewController lifecycle (viewDidLoad, viewDidAppear, viewWillAppear) method 35 | // if none of them are specified, then it's okay, you won't get any error or crash for them 36 | // just like UIKit huh... 37 | // 38 | 39 | 40 | // 41 | // this function will whenever the view controller appeared. 42 | // if transition animation is implemented, then this method 43 | // will be called on the selectedViewController right after the 44 | // animation completed. If no animation provided, it will be called 45 | // just after placing everything in the right place. In either case 46 | // this method will be called after everything is done. 47 | // 48 | -(void)viewControllerDidAppearAnimationFinishedInTabbar:(RSCustomTabbarControllerBasic *)customTabbar 49 | atIndex:(NSUInteger)index; 50 | 51 | @end 52 | 53 | 54 | 55 | #endif /* RSCustomTabbarLifecycleDelegte_h */ 56 | -------------------------------------------------------------------------------- /RSCustomTabbarController/CustomTabbarConroller/RSCustomTabbarTransitionAnimationDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // RSCustomTabbarTransitionAnimationDelegate.h 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 10/2/16. 6 | // Copyright © 2016 funtoos. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #ifndef RSCustomTabbarTransitionAnimationDelegate_h 24 | #define RSCustomTabbarTransitionAnimationDelegate_h 25 | 26 | #import 27 | 28 | // 29 | // Forward declaration of the class, 30 | // to be used in the delegate method 31 | // param 32 | // 33 | @class RSCustomTabbarControllerBasic; 34 | 35 | // 36 | // Declaration of the code block type 37 | // to be used in the delegate method 38 | // param 39 | // 40 | typedef void (^RSCustomTabbarGeneralPurposeBlock)(); 41 | 42 | @protocol RSCustomTabbarTransitionAnimationDelegate 43 | 44 | -(void)customTabbarController:(RSCustomTabbarControllerBasic*)tabbarController 45 | willSwitchFromIndex:(NSUInteger)oldIndex 46 | willSwitchToIndex:(NSUInteger)newIndex 47 | withAnimationCompletionBlock:(RSCustomTabbarGeneralPurposeBlock)completionBlock; 48 | 49 | // 50 | // TODO : another animation delegate needed to be added, 51 | // in case of removing view controller from the container 52 | // 53 | -(void)customTabbarController:(RSCustomTabbarControllerBasic*)tabbarController 54 | willRemoveViewControllers:(NSArray*)removingViewControllers 55 | withCompletionBlock:(RSCustomTabbarGeneralPurposeBlock)completionBlock; 56 | 57 | @end 58 | 59 | 60 | #endif /* RSCustomTabbarTransitionAnimationDelegate_h */ 61 | -------------------------------------------------------------------------------- /RSCustomTabbarController/common/ChildVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // ChildVC.m 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 8/30/16. 6 | // Copyright © 2016 funtoos. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "ChildVC.h" 24 | #import "AppDelegate.h" 25 | 26 | @interface ChildVC () 27 | 28 | @end 29 | 30 | @implementation ChildVC 31 | 32 | - (void)viewDidLoad { 33 | [super viewDidLoad]; 34 | // Do any additional setup after loading the view. 35 | } 36 | 37 | - (void)didReceiveMemoryWarning { 38 | [super didReceiveMemoryWarning]; 39 | // Dispose of any resources that can be recreated. 40 | } 41 | 42 | /* 43 | #pragma mark - Navigation 44 | 45 | // In a storyboard-based application, you will often want to do a little preparation before navigation 46 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 47 | // Get the new view controller using [segue destinationViewController]. 48 | // Pass the selected object to the new view controller. 49 | } 50 | */ 51 | 52 | #pragma mark IBAction 53 | - (IBAction)onBottomSwitchValueChanged:(UISwitch*)sender 54 | { 55 | AppDelegate *appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate; 56 | RSCustomTabbarController *tabbarController = [appDelegate getCurrentCustomTabbarController]; 57 | [tabbarController setTabbarVisibility:sender.isOn animated:YES]; 58 | } 59 | 60 | - (IBAction)backToDemoList:(UIButton*)sender 61 | { 62 | [AppDelegate moveToMenuTableViewController]; 63 | } 64 | 65 | #pragma mark lifecycle delegate 66 | -(void)viewControllerDidAppearAnimationFinishedInTabbar:(RSCustomTabbarControllerBasic *)customTabbar 67 | atIndex:(NSUInteger)index 68 | { 69 | NSLog(@"view controller did appear animation %d", index); 70 | } 71 | 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Demo Transition Animation/SlidingTabbarTransitionAnimation.m: -------------------------------------------------------------------------------- 1 | // 2 | // SlidingTabbarTransitionAnimation.m 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 9/26/16. 6 | // Copyright © 2016 funtoos. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "SlidingTabbarTransitionAnimation.h" 24 | #import "RSCustomTabbarController.h" 25 | 26 | @implementation SlidingTabbarTransitionAnimation 27 | 28 | -(void)customTabbarController:(RSCustomTabbarControllerBasic *)tabbarController 29 | willSwitchFromIndex:(NSUInteger)oldIndex 30 | willSwitchToIndex:(NSUInteger)newIndex 31 | withAnimationCompletionBlock:(RSCustomTabbarGeneralPurposeBlock)completionBlock 32 | { 33 | [[UIApplication sharedApplication] beginIgnoringInteractionEvents]; 34 | 35 | UIViewController *toViewController = [tabbarController getViewControllerAtIndex:newIndex]; 36 | CGRect finalFrame = [(RSCustomTabbarController*)tabbarController getViewControllerContainerFrame]; 37 | 38 | toViewController.view.alpha = 0.0; 39 | toViewController.view.frame = CGRectMake((newIndex > oldIndex) ? finalFrame.size.width : -finalFrame.size.width, 40 | finalFrame.origin.y, 41 | finalFrame.size.width, 42 | finalFrame.size.height); 43 | 44 | 45 | 46 | [UIView animateWithDuration:0.3 animations:^{ 47 | 48 | toViewController.view.frame = finalFrame; 49 | toViewController.view.alpha = 1.0; 50 | 51 | } completion:^(BOOL finished) { 52 | 53 | if(completionBlock) 54 | completionBlock(); 55 | 56 | [[UIApplication sharedApplication] endIgnoringInteractionEvents]; 57 | }]; 58 | } 59 | @end 60 | -------------------------------------------------------------------------------- /RSCustomTabbarController/common/BrowserChildVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // BrowserChildVC.m 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 10/8/16. 6 | // Copyright © 2016 funtoos. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "BrowserChildVC.h" 24 | 25 | @interface BrowserChildVC () 26 | 27 | @end 28 | 29 | @implementation BrowserChildVC 30 | { 31 | 32 | IBOutlet UITextField *mViewAddressTextField; 33 | IBOutlet UIWebView *mViewWebView; 34 | } 35 | 36 | 37 | - (void)viewDidLoad { 38 | [super viewDidLoad]; 39 | // Do any additional setup after loading the view. 40 | } 41 | 42 | - (void)didReceiveMemoryWarning { 43 | [super didReceiveMemoryWarning]; 44 | // Dispose of any resources that can be recreated. 45 | } 46 | 47 | 48 | /* 49 | #pragma mark - Navigation 50 | 51 | // In a storyboard-based application, you will often want to do a little preparation before navigation 52 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 53 | // Get the new view controller using [segue destinationViewController]. 54 | // Pass the selected object to the new view controller. 55 | } 56 | */ 57 | 58 | #pragma mark UITextFieldDelegate 59 | - (BOOL)textFieldShouldReturn:(UITextField *)textField 60 | { 61 | 62 | [self loadThePage:textField.text]; 63 | 64 | 65 | // 66 | // yes we handled it here :) 67 | // 68 | return YES; 69 | } 70 | 71 | #pragma mark IBAction 72 | - (IBAction)onGoBtnPress:(id)sender 73 | { 74 | [self loadThePage:mViewAddressTextField.text]; 75 | } 76 | 77 | 78 | #pragma mark private method 79 | -(void)loadThePage:(NSString*)siteUrl 80 | { 81 | NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:siteUrl]]; 82 | [mViewWebView loadRequest:request]; 83 | 84 | [mViewAddressTextField resignFirstResponder]; 85 | } 86 | 87 | 88 | @end 89 | -------------------------------------------------------------------------------- /RSCustomTabbarController/CustomTabbarConroller/RSCustomTabbarControllerBasic.h: -------------------------------------------------------------------------------- 1 | // 2 | // RSCustomTabbarControllerBasic.h 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 11/6/16. 6 | // Copyright © 2016 funtoos. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | #import "RSCustomTabbarTransitionAnimationDelegate.h" 25 | #import "RSCustomTabbarImplementationDelegate.h" 26 | #import "RSCustomTabbarDelegate.h" 27 | #import "RSCustomTabbarControllerLifecycleDelegte.h" 28 | 29 | #define RSCT_ERROR(msg) NSLog(@"");\ 30 | NSLog(@"***********************ERROR*************************");\ 31 | NSLog(@"%@", msg);\ 32 | NSLog(@"*****************************************************");\ 33 | NSLog(@""); 34 | 35 | // 36 | // specifying if none initial view controller is set 37 | // which view controller will be the initial, 38 | // here the index of the view controller is specified 39 | // 40 | #define CUSTOM_TABBAR_INITIAL_VIEWCONTROLLER_INDEX 0 41 | 42 | #define DEFAULT_SELECTED_INDEX_WHILE_NOTHING_ON_CONTAINER -1 43 | 44 | 45 | @interface RSCustomTabbarControllerBasic : UIViewController 46 | { 47 | NSArray *viewControllers; 48 | NSInteger selectedIndex; 49 | } 50 | 51 | @property id implementationDelegate; 52 | @property id transitionAnimationDelegate; 53 | @property id delegate; 54 | 55 | 56 | -(void)setShouldSelectDefaultViewController:(BOOL)shouldSelect; 57 | -(void)setViewControllers:(NSArray*)vcs; 58 | -(void)setSelectedViewCotnrollerAtIndex:(NSUInteger)index; 59 | -(void)setTabbarVisibility:(BOOL)visible animated:(BOOL)animated; 60 | 61 | -(UIViewController *)getViewControllerAtIndex:(NSUInteger)index; 62 | -(UIViewController *)getSelectedViewController; 63 | -(NSInteger)getSelectedIndex; 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Demo1/Demo1TabbarController.m: -------------------------------------------------------------------------------- 1 | // 2 | // Demo1TabbarController.m 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 8/29/16. 6 | // Copyright © 2016 funtoos. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "Demo1TabbarController.h" 24 | #import "FadingTabbarTransitionAnimation.h" 25 | #import "SlidingTabbarTransitionAnimation.h" 26 | 27 | @interface Demo1TabbarController () 28 | { 29 | NSArray *buttonArr; 30 | } 31 | @property (strong, nonatomic) IBOutlet UIButton *mViewBtn0; 32 | @property (strong, nonatomic) IBOutlet UIButton *mViewBtn1; 33 | @property (strong, nonatomic) IBOutlet UIButton *mViewBtn2; 34 | @property (strong, nonatomic) IBOutlet UIButton *mViewBtn3; 35 | 36 | @end 37 | 38 | @implementation Demo1TabbarController 39 | 40 | 41 | 42 | 43 | #pragma mark life cycle 44 | -(void)viewDidLoad 45 | { 46 | _mViewBtn0.tag = 0; 47 | _mViewBtn1.tag = 1; 48 | _mViewBtn2.tag = 2; 49 | _mViewBtn3.tag = 3; 50 | 51 | 52 | buttonArr = @[_mViewBtn0, _mViewBtn1, _mViewBtn2, _mViewBtn3]; 53 | 54 | super.transitionAnimationDelegate = [SlidingTabbarTransitionAnimation new]; 55 | 56 | [super viewDidLoad]; 57 | } 58 | 59 | 60 | #pragma mark CustomTabbarImplementationDelegate 61 | -(CGFloat)heightForTabbarController:(RSCustomTabbarController*)tabbarController 62 | { 63 | return 56; 64 | } 65 | -(void)newSelectedTabbarIndex:(NSUInteger)newSelectedIndex whereOldIndexWas:(NSUInteger)oldSelectedIndex 66 | { 67 | if(newSelectedIndex == oldSelectedIndex) 68 | { 69 | //it's for the first time 70 | buttonArr[newSelectedIndex].selected = YES; 71 | } 72 | else 73 | { 74 | buttonArr[oldSelectedIndex].selected = NO; 75 | buttonArr[newSelectedIndex].selected = YES; 76 | } 77 | } 78 | 79 | 80 | 81 | 82 | #pragma mark IBActions 83 | -(IBAction)tabbarButtonPressed:(UIButton*)sender 84 | { 85 | NSLog(@"tabbar button pressed"); 86 | [super setSelectedViewCotnrollerAtIndex:sender.tag]; 87 | } 88 | 89 | 90 | @end 91 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Demo Transition Animation/JumpInTabbarTransitionAnimation.m: -------------------------------------------------------------------------------- 1 | // 2 | // JumpInTabbarTransitionAnimation.m 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 9/27/16. 6 | // Copyright © 2016 funtoos. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "JumpInTabbarTransitionAnimation.h" 24 | #import "RSCustomTabbarController.h" 25 | 26 | @implementation JumpInTabbarTransitionAnimation 27 | 28 | 29 | -(void)customTabbarController:(RSCustomTabbarControllerBasic *)tabbarController 30 | willSwitchFromIndex:(NSUInteger)oldIndex 31 | willSwitchToIndex:(NSUInteger)newIndex 32 | withAnimationCompletionBlock:(RSCustomTabbarGeneralPurposeBlock)completionBlock 33 | { 34 | [[UIApplication sharedApplication] beginIgnoringInteractionEvents]; 35 | 36 | UIViewController *toViewController = [tabbarController getViewControllerAtIndex:newIndex]; 37 | CGRect finalFrame = [(RSCustomTabbarController*)tabbarController getViewControllerContainerFrame]; 38 | 39 | toViewController.view.alpha = 0.0; 40 | toViewController.view.frame = finalFrame; 41 | toViewController.view.center = [self getCenterPointOfRect:finalFrame accordingtoIndex:newIndex]; 42 | 43 | [toViewController.view layoutIfNeeded]; 44 | CALayer *viewLayer = toViewController.view.layer; 45 | viewLayer.transform = CATransform3DMakeScale(0, 0, 1); 46 | 47 | [UIView animateWithDuration:0.4 animations:^{ 48 | viewLayer.transform = CATransform3DIdentity; 49 | toViewController.view.center = CGPointMake(CGRectGetMidX(finalFrame), CGRectGetMidY(finalFrame)); 50 | toViewController.view.alpha = 1.0; 51 | } completion:^(BOOL finished) { 52 | 53 | if(completionBlock) 54 | completionBlock(); 55 | 56 | [[UIApplication sharedApplication] endIgnoringInteractionEvents]; 57 | }]; 58 | } 59 | 60 | #pragma mark private helper method 61 | -(CGPoint)getCenterPointOfRect:(CGRect)frame accordingtoIndex:(NSUInteger)index 62 | { 63 | CGPoint center; 64 | 65 | switch (index) { 66 | case 0: 67 | { 68 | center = CGPointMake(CGRectGetMinX(frame), CGRectGetMinY(frame)); 69 | } 70 | break; 71 | case 1: 72 | { 73 | center = CGPointMake(CGRectGetMaxX(frame), CGRectGetMinY(frame)); 74 | } 75 | break; 76 | case 2: 77 | { 78 | center = CGPointMake(CGRectGetMaxX(frame), CGRectGetMaxY(frame)); 79 | } 80 | break; 81 | case 3: 82 | { 83 | center = CGPointMake(CGRectGetMinX(frame), CGRectGetMaxY(frame)); 84 | } 85 | break; 86 | 87 | default: 88 | center = CGPointMake(CGRectGetMidX(frame), CGRectGetMidY(frame)); 89 | break; 90 | } 91 | 92 | return center; 93 | } 94 | @end 95 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Demo Transition Animation/FadingTabbarTransitionAnimation.m: -------------------------------------------------------------------------------- 1 | // 2 | // FadingTabbarTransitionAnimation.m 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 9/23/16. 6 | // Copyright © 2016 funtoos. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "FadingTabbarTransitionAnimation.h" 24 | #import "RSCustomTabbarController.h" 25 | 26 | @implementation FadingTabbarTransitionAnimation 27 | 28 | -(void)customTabbarController:(RSCustomTabbarControllerBasic *)tabbarController 29 | willSwitchFromIndex:(NSUInteger)oldIndex 30 | willSwitchToIndex:(NSUInteger)newIndex 31 | withAnimationCompletionBlock:(RSCustomTabbarGeneralPurposeBlock)completionBlock 32 | { 33 | [[UIApplication sharedApplication] beginIgnoringInteractionEvents]; 34 | 35 | UIViewController *toViewController = [tabbarController getViewControllerAtIndex:newIndex]; 36 | 37 | // 38 | // for the first time, while there are no view controller 39 | // present, both old & new index will denote the same 40 | // view controller 41 | // 42 | UIViewController *fromViewController = nil; 43 | if(newIndex != oldIndex) 44 | fromViewController = [tabbarController getViewControllerAtIndex:oldIndex]; 45 | 46 | toViewController.view.alpha = 0.0; 47 | toViewController.view.frame = [(RSCustomTabbarController*)tabbarController getViewControllerContainerFrame]; 48 | 49 | if(fromViewController) 50 | fromViewController.view.alpha = 1.0; 51 | 52 | [UIView animateWithDuration:0.6 animations:^{ 53 | 54 | toViewController.view.alpha = 1.0; 55 | 56 | if(fromViewController) 57 | fromViewController.view.alpha = 0.0; 58 | 59 | } completion:^(BOOL finished) { 60 | 61 | if(fromViewController) 62 | fromViewController.view.alpha = 1.0; 63 | 64 | if(completionBlock) 65 | completionBlock(); 66 | 67 | [[UIApplication sharedApplication] endIgnoringInteractionEvents]; 68 | }]; 69 | } 70 | 71 | -(void)customTabbarController:(RSCustomTabbarControllerBasic *)tabbarController 72 | willRemoveViewControllers:(NSArray*)removingViewControllers 73 | withCompletionBlock:(RSCustomTabbarGeneralPurposeBlock)completionBlock 74 | { 75 | [[UIApplication sharedApplication] beginIgnoringInteractionEvents]; 76 | 77 | [UIView animateWithDuration:0.6 animations:^{ 78 | 79 | for(UIViewController *removingViewController in removingViewControllers) 80 | removingViewController.view.alpha = 0.0; 81 | 82 | } completion:^(BOOL finished) { 83 | if(completionBlock) 84 | completionBlock(); 85 | 86 | for(UIViewController *removingViewController in removingViewControllers) 87 | removingViewController.view.alpha = 0.0; 88 | 89 | [[UIApplication sharedApplication] endIgnoringInteractionEvents]; 90 | }]; 91 | } 92 | 93 | 94 | @end 95 | -------------------------------------------------------------------------------- /RSCustomTabbarController/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // CustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 8/29/16. 6 | // Copyright © 2016 funtoos. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "AppDelegate.h" 24 | 25 | 26 | @interface AppDelegate () 27 | { 28 | RSCustomTabbarController *tabbarController; 29 | UINavigationController *navController; 30 | } 31 | @end 32 | 33 | @implementation AppDelegate 34 | 35 | 36 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 37 | // Override point for customization after application launch. 38 | 39 | 40 | return YES; 41 | } 42 | 43 | - (void)applicationWillResignActive:(UIApplication *)application { 44 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 45 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 46 | } 47 | 48 | - (void)applicationDidEnterBackground:(UIApplication *)application { 49 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 50 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 51 | } 52 | 53 | - (void)applicationWillEnterForeground:(UIApplication *)application { 54 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 55 | } 56 | 57 | - (void)applicationDidBecomeActive:(UIApplication *)application { 58 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 59 | } 60 | 61 | - (void)applicationWillTerminate:(UIApplication *)application { 62 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 63 | } 64 | 65 | #pragma mark public method 66 | -(void)setCurrentCustomTabbarController:(RSCustomTabbarController*)tc 67 | { 68 | tabbarController = tc; 69 | } 70 | -(RSCustomTabbarController*)getCurrentCustomTabbarController 71 | { 72 | return tabbarController; 73 | } 74 | 75 | -(void)setCurrentNavigationController:(UINavigationController*)navigationController 76 | { 77 | navController = navigationController; 78 | } 79 | -(UINavigationController*)getCurrentNavigationController 80 | { 81 | return navController; 82 | } 83 | 84 | 85 | #pragma mark public class method 86 | +(void)moveToMenuTableViewController 87 | { 88 | AppDelegate *appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate; 89 | UINavigationController *navController = [appDelegate getCurrentNavigationController]; 90 | [navController popToRootViewControllerAnimated:YES]; 91 | } 92 | 93 | 94 | 95 | @end 96 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Demo Transition Animation/PopupTabbarTransitionAnimation.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PopupTabbarTransitionAnimation.swift 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 10/23/16. 6 | // Copyright © 2016 funtoos. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | import Foundation 24 | 25 | // 26 | // for some wierd reason, all sort of objective-c protocol are not 27 | // directly compatible to be implemented vai swift, here i have to introduce 28 | // an objective-c mapping. I have came upon this solution from following 29 | // 30 | // http://stackoverflow.com/questions/31832147/swift-class-does-not-conform-to-objective-c-protocol-with-error-handling 31 | // 32 | 33 | 34 | class PopupTabbarTransitionAnimation : NSObject, RSCustomTabbarTransitionAnimationDelegate 35 | { 36 | 37 | // 38 | // MARK: objective-c mapping for the following method implementation 39 | // 40 | @objc(customTabbarController: 41 | willSwitchFromIndex: 42 | willSwitchToIndex: 43 | withAnimationCompletionBlock:) 44 | 45 | func customTabbarController(_ tabbarController: RSCustomTabbarControllerBasic!, willSwitchFrom oldIndex: UInt, willSwitchTo newIndex: UInt, withAnimationCompletionBlock completionBlock: RSCustomTabbarGeneralPurposeBlock!) { 46 | 47 | // 48 | // turning off all user interaction handling by app 49 | // without these, unusual behaviour may appear 50 | // while switching tab too fast 51 | // 52 | UIApplication.shared.beginIgnoringInteractionEvents(); 53 | 54 | let tabbar = tabbarController as! RSCustomTabbarController; 55 | 56 | let toViewController = tabbarController.getViewController(at: newIndex); 57 | 58 | toViewController?.view.frame = tabbar.getViewControllerContainerFrame(); 59 | toViewController?.view.layer.transform = CATransform3DMakeScale(0, 0, 0); 60 | 61 | UIView.animate(withDuration: 0.5, animations: { 62 | 63 | // 64 | // do the animation here 65 | // 66 | toViewController?.view.layer.transform = CATransform3DIdentity; 67 | 68 | 69 | }, completion: { (completed) in 70 | 71 | // 72 | // animation completed do the completion stuff 73 | // 74 | completionBlock(); 75 | 76 | // 77 | // all the task are done, we should enable user interaction 78 | // 79 | UIApplication.shared.endIgnoringInteractionEvents(); 80 | }) ; 81 | } 82 | 83 | 84 | // 85 | // MARK: objective-c mapping for the following method 86 | // 87 | @objc(customTabbarController: 88 | willRemoveViewControllers: 89 | withCompletionBlock:) 90 | 91 | func customTabbarController(_ tabbarController: RSCustomTabbarControllerBasic!, willRemove removingViewControllers: [UIViewController]!, withCompletionBlock completionBlock: RSCustomTabbarGeneralPurposeBlock!) { 92 | // 93 | // we are not handling any dynamic tab deletion 94 | // in case of any dynamic tab deletion, this protocol must be 95 | // implemented to get the desired effect 96 | // 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /RSCustomTabbarController/CustomTabbarConroller/RSCustomTabbarDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // RSCustomTabbarDelegate.h 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 10/2/16. 6 | // Copyright © 2016 funtoos. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #ifndef RSCustomTabbarDelegate_h 24 | #define RSCustomTabbarDelegate_h 25 | 26 | // 27 | // Forward declaration of the class, 28 | // to be used in the delegate method 29 | // param 30 | // 31 | @class RSCustomTabbarControllerBasic; 32 | 33 | @protocol RSCustomTabbarDelegate 34 | @optional 35 | 36 | // 37 | // @return value will denote that, should the customTabbar show the default specified 38 | // view controller denoted by CUSTOM_TABBAR_INITIAL_VIEWCONTROLLER_INDEX or the delegate 39 | // will automatically select an view controller. 40 | // 41 | // @discussion 42 | // 43 | // If you select a view controller inside the delegate, you should return NO, so that, 44 | // viewDidLoad inside the RSCustomTabbarController won't try to show up the default 45 | // view controller denoted by the CUSTOM_TABBAR_INITIAL_VIEWCONTROLLER_INDEX. 46 | // Else should return YES, otherwise no view controller won't be present at front. 47 | // If this delegate is not implemented then, RSCustomTabbarController will load the 48 | // view controller denote by the CUSTOM_TABBAR_INITIAL_VIEWCONTROLLER_INDEX 49 | // 50 | - (void)customTabbarControllerViewDidLoaded:(RSCustomTabbarControllerBasic *)tabBarController; 51 | 52 | 53 | 54 | #pragma mark Unimplemented delegate methods 55 | //- (BOOL)customTabbarController:(CustomTabbarController *)tabBarController 56 | // willSelectViewController:(UIViewController *)viewController; 57 | // 58 | //- (void)customTabbarController:(CustomTabbarController *)tabBarController 59 | // didSelectViewController:(UIViewController *)viewController; 60 | 61 | //- (void)customTabBarController:(CustomTabbarController *)tabBarController 62 | //willBeginCustomizingViewControllers:(NSArray<__kindof UIViewController *> *)viewControllers NS_AVAILABLE_IOS(3_0) __TVOS_PROHIBITED; 63 | 64 | //- (void)tabBarController:(UITabBarController *)tabBarController willEndCustomizingViewControllers:(NSArray<__kindof UIViewController *> *)viewControllers changed:(BOOL)changed NS_AVAILABLE_IOS(3_0) __TVOS_PROHIBITED; 65 | 66 | //- (void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray<__kindof UIViewController *> *)viewControllers changed:(BOOL)changed __TVOS_PROHIBITED; 67 | 68 | //- (UIInterfaceOrientationMask)tabBarControllerSupportedInterfaceOrientations:(UITabBarController *)tabBarController NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED; 69 | //- (UIInterfaceOrientation)tabBarControllerPreferredInterfaceOrientationForPresentation:(UITabBarController *)tabBarController NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED; 70 | //- (nullable id )tabBarController:(UITabBarController *)tabBarController 71 | // interactionControllerForAnimationController: (id )animationController NS_AVAILABLE_IOS(7_0); 72 | // 73 | //- (nullable id )tabBarController:(UITabBarController *)tabBarController 74 | // animationControllerForTransitionFromViewController:(UIViewController *)fromVC 75 | // toViewController:(UIViewController *)toVC NS_AVAILABLE_IOS(7_0); 76 | 77 | @end 78 | 79 | 80 | #endif /* RSCustomTabbarDelegate_h */ 81 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Demo2/Demo2TabbarController.m: -------------------------------------------------------------------------------- 1 | // 2 | // Demo2TabbarController.m 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 8/31/16. 6 | // Copyright © 2016 funtoos. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "Demo2TabbarController.h" 24 | #import "JumpInTabbarTransitionAnimation.h" 25 | 26 | @interface Demo2TabbarController () 27 | { 28 | IBOutlet UIButton *barBtn0; 29 | IBOutlet UIButton *barBtn1; 30 | IBOutlet UIButton *barBtn2; 31 | IBOutlet UIButton *barBtn3; 32 | 33 | NSArray *allBtns; 34 | 35 | IBOutlet UIView *tabbar0; 36 | IBOutlet UIView *tabbar1; 37 | IBOutlet UIView *tabbar2; 38 | IBOutlet UIView *tabbar3; 39 | 40 | NSArray *allTabbar; 41 | } 42 | 43 | 44 | 45 | @end 46 | 47 | @implementation Demo2TabbarController 48 | 49 | - (void)viewDidLoad { 50 | 51 | allBtns = @[ 52 | barBtn0, 53 | barBtn1, 54 | barBtn2, 55 | barBtn3 56 | ]; 57 | 58 | allTabbar = @[ 59 | tabbar0, 60 | tabbar1, 61 | tabbar2, 62 | tabbar3 63 | ]; 64 | 65 | barBtn0.tag = 0; 66 | barBtn1.tag = 1; 67 | barBtn2.tag = 2; 68 | barBtn3.tag = 3; 69 | 70 | [[UIApplication sharedApplication] setStatusBarHidden:YES 71 | withAnimation:UIStatusBarAnimationFade]; 72 | 73 | 74 | super.transitionAnimationDelegate = [JumpInTabbarTransitionAnimation new]; 75 | 76 | 77 | [super viewDidLoad]; 78 | } 79 | 80 | - (BOOL)prefersStatusBarHidden { 81 | return YES; 82 | } 83 | 84 | /* 85 | #pragma mark - Navigation 86 | 87 | // In a storyboard-based application, you will often want to do a little preparation before navigation 88 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 89 | // Get the new view controller using [segue destinationViewController]. 90 | // Pass the selected object to the new view controller. 91 | } 92 | */ 93 | 94 | #pragma mark IBAction 95 | -(IBAction)onTabbarButtonPressed:(UIButton*)sender 96 | { 97 | [super setSelectedViewCotnrollerAtIndex:sender.tag]; 98 | } 99 | 100 | 101 | 102 | #pragma mark CustomTabbarImplementationDelegate 103 | -(CGFloat)heightForTabbarController:(RSCustomTabbarController*)tabbarController 104 | { 105 | return 200; 106 | } 107 | -(void)newSelectedTabbarIndex:(NSUInteger)newSelectedIndex 108 | whereOldIndexWas:(NSUInteger)oldSelectedIndex 109 | { 110 | 111 | if(oldSelectedIndex == newSelectedIndex) 112 | { 113 | // 114 | // this situation happened for the first time only, 115 | // because we dont want to add another function 116 | // for this callback, thats how we sharing the 117 | // function 118 | // 119 | allBtns[newSelectedIndex].selected = YES; 120 | allTabbar[newSelectedIndex].backgroundColor = [UIColor whiteColor]; 121 | } 122 | else 123 | { 124 | allBtns[newSelectedIndex].selected = YES; 125 | allBtns[oldSelectedIndex].selected = NO; 126 | 127 | allTabbar[newSelectedIndex].backgroundColor = [UIColor whiteColor]; 128 | allTabbar[oldSelectedIndex].backgroundColor = [UIColor lightGrayColor]; 129 | } 130 | 131 | 132 | } 133 | 134 | @end 135 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RSCustomTabbarController 2 | This is super flexible Custom tab bar controller implementation. You have the complete opportunity to customise according to your necessity. 3 | 4 | ## Want to check on your own ? 5 | Experience a **[live demonstration](https://appetize.io/app/nqd9py0znzmgar66cxtfw7vxzc?device=iphone5s&scale=75&orientation=portrait&osVersion=9.3)** 6 | 7 | ## Simple Demonstration 8 | You can design whatever tabbar controller comes in your mind. Following is some simple demonstration. Many more are yet to come. If you have any unique idea, you would like to implement it for you feel free to contact Sharker.ratul.08@gmail.com 9 | 10 | 11 | 12 | ## Simple tutorial 13 | 14 | ###Step1: 15 | Copy the [RSCustomTabbarController](https://github.com/ratulSharker/RSCustomTabbarController/tree/master/RSCustomTabbarController/CustomTabbarConroller) in your project. 16 | 17 | ###Step2: 18 | Create a new class extending from the base class `RSCustomTabbarController`. Let the new class name is `Demo1TabbarController`. 19 | `Demo1TabbarController.h` looks like following. 20 | 21 | ```obj-c 22 | #import 23 | #import "RSCustomTabbarController.h" 24 | 25 | @interface Demo1TabbarController : RSCustomTabbarController 26 | 27 | @end 28 | ``` 29 | Now implement the `RSCustomTabbarImplementationDelegate` by adding following properties & methods in `Demo1TabbarController` 30 | 31 | ```obj-c 32 | @property UIView *viewControllerContainer; 33 | 34 | @property NSArray *tabbarContainerHeight; 35 | @property NSArray *tabbarWidgetHolderTop; 36 | 37 | -(CGFloat)heightForTabbarController:(RSCustomTabbarController*)tabbarController; 38 | -(void)newSelectedTabbarIndex:(NSUInteger)newSelectedIndex whereOldIndexWas:(NSUInteger)oldSelectedIndex; 39 | ``` 40 | 41 | Before getting into nitty gitty details, first grab some key concept about this protocol. This `RSCustomTabbarImplentationDelegate` will 42 | ask for these 3 properties & 2 method. You are about to apply your own graphical design, but how should `RSCustomTabbarController` would 43 | know about which is your view controller container and what will act as an tabbar container. Thats why this protocol is designed to communicate between your provided presentation and internal tabbar like maintanance. 44 | 45 | now the `Demo1TabbarController.h` is looks like 46 | ```obj-c 47 | #import 48 | #import "RSCustomTabbarController.h" 49 | 50 | @interface Demo1TabbarController : RSCustomTabbarController 51 | 52 | #pragma mark implementation properties 53 | @property IBOutlet UIView *viewControllerContainer; 54 | @property IBOutletCollection (NSLayoutConstraint) NSArray *tabbarContainerHeight; 55 | @property IBOutletCollection (NSLayoutConstraint) NSArray *tabbarWidgetHolderTop; 56 | 57 | @end 58 | ``` 59 | 60 | and the `Demo1TabbarController.m` will look like 61 | ```obj-c 62 | #import "Demo1TabbarController.h" 63 | 64 | @interface Demo1TabbarController () 65 | 66 | @end 67 | 68 | @implementation Demo1TabbarController 69 | 70 | #pragma mark life cycle 71 | -(void)viewDidLoad 72 | { 73 | [super viewDidLoad]; 74 | } 75 | 76 | #pragma mark CustomTabbarImplementationDelegate 77 | -(CGFloat)heightForTabbarController:(RSCustomTabbarController*)tabbarController 78 | { 79 | //todo -- implementation 80 | } 81 | -(void)newSelectedTabbarIndex:(NSUInteger)newSelectedIndex whereOldIndexWas:(NSUInteger)oldSelectedIndex 82 | { 83 | //todo -- implementation 84 | } 85 | @end 86 | ``` 87 | 88 | For now we are done with class. Now we need to add a inteface builder file (storyboard/nib) file for designing the tabbar controller. 89 | Following is the hierarchy we will be following to create the `Demo1TabbarContorller` 90 | 91 | ``` 92 | UIVIewController 93 | | 94 | |--> self.view 95 | | 96 | |--> viewController container 97 | |--> tabbar container 98 | | 99 | |--> bar button container 100 | | 101 | |--> buttons 102 | ``` 103 | 104 | Storyboard designing can be done as followos 105 | 106 | [![Checkout at youtube](https://img.youtube.com/vi/8Yq26NWsHVo/0.jpg)](https://www.youtube.com/watch?v=8Yq26NWsHVo) 107 | 108 | After done with your designing, now add some `IBOutlets`, `IBactions` and variables in the `Demo1TabbarController.m`. It should look like following 109 | 110 | ```obj-c 111 | #import "Demo1TabbarController.h" 112 | 113 | @interface Demo1TabbarController () 114 | { 115 | NSArray *buttonArr; 116 | } 117 | @property (strong, nonatomic) IBOutlet UIButton *mViewBtn0; 118 | @property (strong, nonatomic) IBOutlet UIButton *mViewBtn1; 119 | @property (strong, nonatomic) IBOutlet UIButton *mViewBtn2; 120 | @property (strong, nonatomic) IBOutlet UIButton *mViewBtn3; 121 | @property (strong, nonatomic) IBOutlet UIButton *mViewBtn4; 122 | 123 | @end 124 | 125 | @implementation Demo1TabbarController 126 | 127 | #pragma mark life cycle 128 | -(void)viewDidLoad 129 | { 130 | _mViewBtn0.tag = 0; 131 | _mViewBtn1.tag = 1; 132 | _mViewBtn2.tag = 2; 133 | _mViewBtn3.tag = 3; 134 | _mViewBtn4.tag = 4; 135 | 136 | 137 | buttonArr = @[_mViewBtn0, _mViewBtn1, _mViewBtn2, _mViewBtn3, _mViewBtn4]; 138 | 139 | [super viewDidLoad]; 140 | } 141 | 142 | 143 | #pragma mark CustomTabbarImplementationDelegate 144 | -(CGFloat)heightForTabbarController:(RSCustomTabbarController*)tabbarController 145 | { 146 | return 95; 147 | } 148 | -(void)newSelectedTabbarIndex:(NSUInteger)newSelectedIndex whereOldIndexWas:(NSUInteger)oldSelectedIndex 149 | { 150 | buttonArr[oldSelectedIndex].selected = NO; 151 | buttonArr[newSelectedIndex].selected = YES; 152 | } 153 | 154 | #pragma mark IBActions 155 | -(IBAction)tabbarButtonPressed:(UIButton*)sender 156 | { 157 | NSLog(@"tabbar button pressed"); 158 | [super setSelectedViewCotnrollerAtIndex:sender.tag]; 159 | } 160 | 161 | @end 162 | ``` 163 | 164 | Now time to connect the IBAction and IBOutlet of the implementation so that the storyboard widgets can map into it. These are shown in the next video. 165 | 166 | [![Checkout at youtube](https://img.youtube.com/vi/kigm5uvIEuo/0.jpg)](https://www.youtube.com/watch?v=kigm5uvIEuo) 167 | 168 | Our custom tabbar is ready to rock and roll. Instantiate it from Storyboard and use it just like regular [UITabbarController](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITabBarController_Class/). 169 | -------------------------------------------------------------------------------- /RSCustomTabbarController/CustomTabbarConroller/RSCustomTabbarController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RSCustomTabbarController.m 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 8/29/16. 6 | // Copyright © 2016 funtoos. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "RSCustomTabbarController.h" 24 | 25 | 26 | 27 | @interface RSCustomTabbarController() 28 | { 29 | NSMutableArray *viewDidLoadPendingBlocks; 30 | } 31 | 32 | @end 33 | 34 | @implementation RSCustomTabbarController 35 | 36 | 37 | #pragma mark UIViewControllerLifeCycle 38 | -(void)viewDidLoad 39 | { 40 | [super viewDidLoad]; 41 | 42 | // 43 | // execute any pending block 44 | // 45 | if(viewDidLoadPendingBlocks && viewDidLoadPendingBlocks.count) 46 | { 47 | for(RSCustomTabbarGeneralPurposeBlock pendingBlock in viewDidLoadPendingBlocks) 48 | { 49 | pendingBlock(); 50 | } 51 | 52 | [viewDidLoadPendingBlocks removeAllObjects]; 53 | } 54 | } 55 | 56 | 57 | #pragma mark public functionality 58 | -(void)addPendingBlockIntendedToBeExecutedAfterViewDidLoad:(RSCustomTabbarGeneralPurposeBlock)block 59 | { 60 | if(!viewDidLoadPendingBlocks) 61 | { 62 | // 63 | // tracker is not initiated yet, but want to track. 64 | // so it's high time to initiate it 65 | // 66 | viewDidLoadPendingBlocks = [[NSMutableArray alloc] init]; 67 | } 68 | 69 | // 70 | // now we got initiated tracker :D , 71 | // just track the pending blocks 72 | // 73 | [viewDidLoadPendingBlocks addObject:block]; 74 | } 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -(void)removeViewControllerFromContainerAtIndex:(NSUInteger)index 83 | { 84 | // 85 | // check that the index is valid or not 86 | // 87 | if(viewControllers && viewControllers.count > index) 88 | { 89 | [self removeViewControllerFromContainer:viewControllers[index]]; 90 | } 91 | else 92 | { 93 | NSLog(@"index is too high, in removeViewControllerFromContainerAtIndex"); 94 | } 95 | } 96 | -(void)removeViewControllerFromContainer:(UIViewController*)viewController 97 | { 98 | if(viewController && viewController.parentViewController == self) 99 | { 100 | RSCustomTabbarGeneralPurposeBlock completionBlock = ^{ 101 | [viewController willMoveToParentViewController:nil]; 102 | [viewController.view removeFromSuperview]; 103 | [viewController removeFromParentViewController]; 104 | selectedIndex = DEFAULT_SELECTED_INDEX_WHILE_NOTHING_ON_CONTAINER; 105 | }; 106 | 107 | if(![self callTranstionAnimationDelegateWillRemoveViewController:@[viewController] 108 | withCompletionBlock:completionBlock]) 109 | { 110 | completionBlock(); 111 | } 112 | 113 | } 114 | else 115 | { 116 | NSLog(@"view controller is not valid or does not belong to this tab container"); 117 | } 118 | } 119 | 120 | -(void)removeAllViewControllerFromContainer 121 | { 122 | 123 | RSCustomTabbarGeneralPurposeBlock completionBlock = ^{ 124 | // though at a time only one child viewcontroller 125 | // will be in existence, but we should remove all 126 | // for sake of generality 127 | for(UIViewController *childVC in self.childViewControllers) 128 | { 129 | [childVC willMoveToParentViewController:nil]; 130 | [childVC.view removeFromSuperview]; 131 | [childVC removeFromParentViewController]; 132 | } 133 | selectedIndex = DEFAULT_SELECTED_INDEX_WHILE_NOTHING_ON_CONTAINER; 134 | }; 135 | 136 | 137 | if(![self callTranstionAnimationDelegateWillRemoveViewController:self.childViewControllers 138 | withCompletionBlock:completionBlock]) 139 | { 140 | completionBlock(); 141 | } 142 | } 143 | 144 | -(BOOL)isViewLoaded 145 | { 146 | return super.isViewLoaded; 147 | } 148 | 149 | 150 | 151 | 152 | 153 | 154 | -(CGRect)getViewControllerContainerFrame 155 | { 156 | CGRect frame = CGRectZero; 157 | 158 | if(self.implementationDelegate && self.implementationDelegate.viewControllerContainer) 159 | { 160 | frame = self.implementationDelegate.viewControllerContainer.bounds; 161 | } 162 | else 163 | { 164 | RSCT_ERROR(@"RSCustomTabbarController implementation delegate is not properly implemented, actually the property 💔 viewControllerContainer 💔 not found"); 165 | } 166 | 167 | return frame; 168 | } 169 | 170 | #pragma mark private helper method 171 | -(BOOL)callTranstionAnimationDelegateWillRemoveViewController:(NSArray*)vcs 172 | withCompletionBlock:(RSCustomTabbarGeneralPurposeBlock)completionBlock 173 | { 174 | if(self.transitionAnimationDelegate && 175 | [self.transitionAnimationDelegate respondsToSelector:@selector(customTabbarController: 176 | willRemoveViewControllers: 177 | withCompletionBlock:)]) 178 | { 179 | [self.transitionAnimationDelegate customTabbarController:self 180 | willRemoveViewControllers:vcs 181 | withCompletionBlock:completionBlock]; 182 | 183 | return YES; 184 | } 185 | else 186 | { 187 | return NO; 188 | } 189 | } 190 | 191 | @end 192 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Demo5/Demo5TabbarController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Demo5TabbarController.swift 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 10/22/16. 6 | // Copyright © 2016 funtoos. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | import Foundation 24 | 25 | let TABBAR_SHOWN_SIZE = 160.0; 26 | let TABBAR_HIDDEN_SIZE = 8.0; 27 | 28 | @objc 29 | class Demo5TabbarController: RSCustomTabbarController, RSCustomTabbarImplementationDelegate 30 | { 31 | 32 | // @property UIView *viewControllerContainer; 33 | // 34 | // @property NSArray *tabbarContainerHeight; 35 | // @property NSArray *tabbarWidgetHolderTop; 36 | // 37 | // -(CGFloat)heightForTabbarController:(RSCustomTabbarController*)tabbarController; 38 | // -(void)newSelectedTabbarIndex:(NSUInteger)newSelectedIndex whereOldIndexWas:(NSUInteger)oldSelectedIndex; 39 | 40 | // 41 | // MARK: RSCustomTabbarImplementationDelegate properties 42 | // 43 | @IBOutlet var viewControllerContainer: UIView! 44 | 45 | // 46 | // MARK: UI Components 47 | // 48 | @IBOutlet var tabbar0: UIButton!; 49 | @IBOutlet var tabbar1: UIButton!; 50 | @IBOutlet var tabbar2: UIButton!; 51 | @IBOutlet var tabbar3: UIButton!; 52 | 53 | @IBOutlet var mViewTabbarHolder: UIView! 54 | @IBOutlet var mViewTabbarHideShowBtn: UIButton! 55 | 56 | 57 | 58 | @IBOutlet var mConstraintTabHolderWidth: NSLayoutConstraint! 59 | 60 | 61 | var tabbars: [UIButton]!; 62 | 63 | 64 | 65 | 66 | 67 | // 68 | // MARK: UIViewController Life-cycle method 69 | // 70 | override func viewDidLoad() { 71 | 72 | // setup the tabbar first 73 | tabbars = [tabbar0, tabbar1, tabbar2, tabbar3]; 74 | 75 | // just fascinated ui things 76 | tabbar0.imageView?.contentMode = UIViewContentMode.scaleAspectFit; 77 | tabbar1.imageView?.contentMode = UIViewContentMode.scaleAspectFit; 78 | tabbar2.imageView?.contentMode = UIViewContentMode.scaleAspectFit; 79 | tabbar3.imageView?.contentMode = UIViewContentMode.scaleAspectFit; 80 | 81 | // storing the index in the tag, so that we can access tabbars faster while handle button actions 82 | tabbar0.tag = 0; 83 | tabbar1.tag = 1; 84 | tabbar2.tag = 2; 85 | tabbar3.tag = 3; 86 | 87 | self.setTabbarVisibility(false, animated: false); 88 | mViewTabbarHideShowBtn.isSelected = true; 89 | 90 | // 91 | // assigning the PopupTabbarTransitionAnimation as a animation handler 92 | // 93 | super.transitionAnimationDelegate = PopupTabbarTransitionAnimation(); 94 | 95 | super.viewDidLoad(); 96 | } 97 | 98 | override func viewWillAppear(_ animated: Bool) { 99 | super.viewWillAppear(animated); 100 | 101 | self.navigationController?.isNavigationBarHidden = true; 102 | 103 | } 104 | 105 | override func viewWillDisappear(_ animated: Bool) { 106 | super.viewWillDisappear(animated); 107 | 108 | self.navigationController?.isNavigationBarHidden = false; 109 | } 110 | 111 | 112 | // 113 | // MARK: RSCustomTabbarController overidden method 114 | // 115 | override func setTabbarVisibility(_ visible: Bool, animated: Bool) { 116 | 117 | if(animated) 118 | { 119 | // be aware need to perform some animation 120 | if(visible) 121 | { 122 | mViewTabbarHolder.alpha = 0.0; 123 | mViewTabbarHolder.isHidden = false; 124 | } 125 | 126 | UIView.animate(withDuration: 0.5, animations: { 127 | 128 | self.mViewTabbarHolder.alpha = visible ? 1.0 : 0.0; 129 | self.mConstraintTabHolderWidth.constant = CGFloat((visible ? TABBAR_SHOWN_SIZE : TABBAR_HIDDEN_SIZE)); 130 | 131 | self.view.layoutIfNeeded(); 132 | 133 | }, completion: { (completed) in 134 | if(!visible) 135 | { 136 | self.mViewTabbarHolder.isHidden = false; 137 | self.mViewTabbarHolder.alpha = 1.0; // restoring alpha 138 | } 139 | }); 140 | } 141 | else 142 | { 143 | // just hide or show, no animation needed 144 | mConstraintTabHolderWidth.constant = CGFloat(visible ? TABBAR_SHOWN_SIZE : TABBAR_HIDDEN_SIZE); 145 | mViewTabbarHolder.isHidden = !visible; 146 | } 147 | 148 | } 149 | 150 | 151 | // 152 | // MARK: RSCustomTabbarImplementationDelegate method 153 | // 154 | func newSelectedTabbarIndex(_ newSelectedIndex: UInt, 155 | whereOldIndexWas oldSelectedIndex: UInt) { 156 | 157 | if(newSelectedIndex == oldSelectedIndex) 158 | { 159 | // 160 | // this is called for the first time 161 | // 162 | tabbars[Int(newSelectedIndex)].isSelected = true; 163 | } 164 | else 165 | { 166 | // 167 | // subsequent call from user interaction 168 | // 169 | tabbars[Int(newSelectedIndex)].isSelected = true; 170 | tabbars[Int(oldSelectedIndex)].isSelected = false; 171 | } 172 | } 173 | 174 | // 175 | // MARK: IBAction Methods 176 | // 177 | @IBAction func onTabbarButtonPressed(_ sender :UIButton!) 178 | { 179 | // 180 | // this call will make the RSCustomTabbarController to 181 | // call the new select old select delegate called. 182 | // All the selection thing will be managed there. 183 | // 184 | super.setSelectedViewCotnrollerAt(UInt(sender.tag)); 185 | } 186 | 187 | @IBAction func onTabbarShowHidePressed(_ sender: UIButton!) 188 | { 189 | sender.isSelected = !sender.isSelected; 190 | 191 | if(sender.isSelected) 192 | { 193 | self.setTabbarVisibility(false, animated: true); 194 | } 195 | else 196 | { 197 | self.setTabbarVisibility(true, animated: true); 198 | } 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Demo6/demo6.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Demo3/Demo3TabbarController.m: -------------------------------------------------------------------------------- 1 | // 2 | // Demo3TabbarController.m 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 9/10/16. 6 | // Copyright © 2016 funtoos. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "Demo3TabbarController.h" 24 | #import "FadingTabbarTransitionAnimation.h" 25 | 26 | #define DRAGGING_TOP_DISTANCE 8 27 | #define DRAGGING_LEADING_DISTANCE 8 28 | 29 | @interface Demo3TabbarController () 30 | { 31 | NSArray *btnArr; 32 | NSArray *tabbarArr; 33 | } 34 | @property (strong, nonatomic) IBOutlet UIButton *tabbarBtn0; 35 | @property (strong, nonatomic) IBOutlet UIButton *tabbarBtn1; 36 | @property (strong, nonatomic) IBOutlet UIButton *tabbarBtn2; 37 | 38 | @property (strong, nonatomic) IBOutlet NSLayoutConstraint *tabbar0Top; 39 | @property (strong, nonatomic) IBOutlet NSLayoutConstraint *tabbar0Leading; 40 | 41 | @property (strong, nonatomic) IBOutlet NSLayoutConstraint *tabbar1Top; 42 | @property (strong, nonatomic) IBOutlet NSLayoutConstraint *tabbar1Leading; 43 | 44 | @property (strong, nonatomic) IBOutlet NSLayoutConstraint *tabbar2Top; 45 | @property (strong, nonatomic) IBOutlet NSLayoutConstraint *tabbar2Leading; 46 | 47 | @property (strong, nonatomic) IBOutlet UIView *tabbarHolder0; 48 | @property (strong, nonatomic) IBOutlet UIView *tabbarHolder1; 49 | @property (strong, nonatomic) IBOutlet UIView *tabbarHolder2; 50 | 51 | @end 52 | 53 | @implementation Demo3TabbarController 54 | 55 | - (void)viewDidLoad { 56 | 57 | _tabbarBtn0.tag = 0; 58 | _tabbarBtn1.tag = 1; 59 | _tabbarBtn2.tag = 2; 60 | 61 | btnArr = @[_tabbarBtn0, 62 | _tabbarBtn1, 63 | _tabbarBtn2]; 64 | 65 | tabbarArr = @[_tabbarHolder0, 66 | _tabbarHolder1, 67 | _tabbarHolder2]; 68 | 69 | // 70 | // providing appropriate transition animation 71 | // 72 | super.transitionAnimationDelegate = [FadingTabbarTransitionAnimation new]; 73 | 74 | 75 | // adding gesture recognizer 76 | [self addGestureRecognizerToTabbars]; 77 | 78 | // 79 | // we want to execute the super view did load 80 | // just after the tags been set 81 | // 82 | [super viewDidLoad]; 83 | 84 | } 85 | 86 | - (void)didReceiveMemoryWarning { 87 | [super didReceiveMemoryWarning]; 88 | // Dispose of any resources that can be recreated. 89 | } 90 | 91 | /* 92 | #pragma mark - Navigation 93 | 94 | // In a storyboard-based application, you will often want to do a little preparation before navigation 95 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 96 | // Get the new view controller using [segue destinationViewController]. 97 | // Pass the selected object to the new view controller. 98 | } 99 | */ 100 | 101 | #pragma mark CustomTabbarImplementationDelegate 102 | -(CGFloat)heightForTabbarController:(RSCustomTabbarController*)tabbarController 103 | { 104 | return 60; 105 | } 106 | 107 | -(void)newSelectedTabbarIndex:(NSUInteger)newSelectedIndex 108 | whereOldIndexWas:(NSUInteger)oldSelectedIndex 109 | { 110 | if(newSelectedIndex != oldSelectedIndex) 111 | { 112 | //simple cases 113 | tabbarArr[oldSelectedIndex].backgroundColor = [UIColor lightGrayColor]; 114 | tabbarArr[newSelectedIndex].backgroundColor = [UIColor whiteColor]; 115 | 116 | btnArr[oldSelectedIndex].selected = NO; 117 | btnArr[newSelectedIndex].selected = YES; 118 | } 119 | else 120 | { 121 | tabbarArr[newSelectedIndex].backgroundColor = [UIColor whiteColor]; 122 | btnArr[newSelectedIndex].selected = YES; 123 | 124 | } 125 | } 126 | 127 | #pragma mark custom implementation 128 | -(void)setTabbarVisibility:(BOOL)visible animated:(BOOL)animated 129 | { 130 | //won't call super here 131 | if(animated){ 132 | [[UIApplication sharedApplication] beginIgnoringInteractionEvents]; 133 | 134 | if(visible){ 135 | [self setAllTabbarHolderVisibility:YES]; 136 | [self setAllTabbarHolderAlphaLevel:0.0]; 137 | } 138 | else{ 139 | [self setAllTabbarHolderAlphaLevel:1.0]; 140 | } 141 | 142 | [UIView animateWithDuration:0.5 143 | animations:^{ 144 | [self setAllTabbarHolderAlphaLevel:(CGFloat)visible]; 145 | } 146 | completion:^(BOOL finished) { 147 | [self setAllTabbarHolderVisibility:visible]; 148 | [self setAllTabbarHolderAlphaLevel:1.0]; 149 | 150 | [[UIApplication sharedApplication] endIgnoringInteractionEvents]; 151 | }]; 152 | } 153 | else 154 | { 155 | [self setAllTabbarHolderVisibility:visible]; 156 | } 157 | } 158 | 159 | #pragma mark IBAction 160 | -(IBAction)onTabbarBtnPressed:(UIButton*)sender 161 | { 162 | [super setSelectedViewCotnrollerAtIndex:sender.tag]; 163 | } 164 | 165 | #pragma mark gesture recongnizer 166 | -(void)panGesture:(UIPanGestureRecognizer*)gesture 167 | { 168 | UIView *holder = gesture.view; 169 | static CGPoint startPoint; 170 | static NSLayoutConstraint *viewLeadingConstraint, *viewTopConstraint; 171 | 172 | switch (gesture.state) { 173 | case UIGestureRecognizerStateBegan:{ 174 | [self gestureStartEndViewSettings:holder isStart:YES]; 175 | startPoint = [gesture locationInView:holder]; 176 | 177 | viewLeadingConstraint = [self getConstraintAccordingToGesture:gesture isLeading:YES]; 178 | viewTopConstraint = [self getConstraintAccordingToGesture:gesture isLeading:NO]; 179 | } 180 | break; 181 | case UIGestureRecognizerStateChanged:{ 182 | //update the view constraint 183 | [self translateViewAccordingToGesture:gesture 184 | withStartPoint:startPoint 185 | leadingConstraint:viewLeadingConstraint 186 | topConstraint:viewTopConstraint]; 187 | } 188 | break; 189 | case UIGestureRecognizerStateEnded: 190 | case UIGestureRecognizerStateFailed: 191 | case UIGestureRecognizerStateCancelled:{ 192 | [self gestureStartEndViewSettings:holder isStart:NO]; 193 | 194 | viewLeadingConstraint = nil; 195 | viewTopConstraint = nil; 196 | startPoint = CGPointZero; 197 | } 198 | 199 | default: 200 | break; 201 | } 202 | } 203 | 204 | #pragma mark private helper methods 205 | -(void)setAllTabbarHolderVisibility:(BOOL)visibility 206 | { 207 | _tabbarHolder0.hidden = _tabbarHolder1.hidden = _tabbarHolder2.hidden = !visibility; 208 | } 209 | -(void)setAllTabbarHolderAlphaLevel:(CGFloat)alpha 210 | { 211 | _tabbarHolder0.alpha = _tabbarHolder1.alpha = _tabbarHolder2.alpha = alpha; 212 | } 213 | -(void)addGestureRecognizerToTabbars 214 | { 215 | for(UIView *tabbarHolder in tabbarArr) 216 | { 217 | [tabbarHolder addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self 218 | action:@selector(panGesture:)]]; 219 | } 220 | } 221 | 222 | // 223 | // here starts all gesture related helper methods 224 | // 225 | -(void)gestureStartEndViewSettings:(UIView*)holderView isStart:(BOOL)gestureStart 226 | { 227 | if(gestureStart) 228 | { 229 | //chnage the view properties to selected 230 | holderView.layer.borderWidth = 3.0; 231 | holderView.layer.borderColor = [UIColor yellowColor].CGColor; 232 | [self.view bringSubviewToFront:holderView]; 233 | } 234 | else 235 | { 236 | //change the view properties to normal 237 | holderView.layer.borderWidth = 0; 238 | holderView.layer.borderColor = [UIColor clearColor].CGColor; 239 | } 240 | } 241 | 242 | -(NSLayoutConstraint*)getConstraintAccordingToGesture:(UIPanGestureRecognizer*)gesture isLeading:(BOOL)isLeading 243 | { 244 | if(gesture.view == _tabbarHolder0) 245 | { 246 | return isLeading ? _tabbar0Leading : _tabbar0Top; 247 | } 248 | else if(gesture.view == _tabbarHolder1) 249 | { 250 | return isLeading ? _tabbar1Leading : _tabbar1Top; 251 | } 252 | else if(gesture.view == _tabbarHolder2) 253 | { 254 | return isLeading ? _tabbar2Leading : _tabbar2Top; 255 | } 256 | return nil; 257 | } 258 | 259 | 260 | -(void)translateViewAccordingToGesture:(UIPanGestureRecognizer *)gesture 261 | withStartPoint:(CGPoint)startPoint 262 | leadingConstraint:(NSLayoutConstraint*)viewLeadingConstraint 263 | topConstraint:(NSLayoutConstraint*)viewTopConstraint 264 | { 265 | //update the view constraint 266 | CGPoint translatedPoint = [gesture locationInView:self.view]; 267 | 268 | translatedPoint.x = translatedPoint.x - startPoint.x; 269 | translatedPoint.y = translatedPoint.y - startPoint.y; 270 | 271 | if(viewLeadingConstraint && translatedPoint.x > DRAGGING_LEADING_DISTANCE) 272 | { 273 | viewLeadingConstraint.constant = translatedPoint.x; 274 | } 275 | 276 | if(viewTopConstraint && translatedPoint.y > DRAGGING_TOP_DISTANCE) 277 | { 278 | viewTopConstraint.constant = translatedPoint.y; 279 | } 280 | 281 | } 282 | 283 | 284 | 285 | @end 286 | -------------------------------------------------------------------------------- /RSCustomTabbarController/menu.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 | 35 | 41 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /RSCustomTabbarController/MenuTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // MenuViewController.m 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 9/2/16. 6 | // Copyright © 2016 funtoos. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "MenuTableViewController.h" 24 | #import "MenuTableCell.h" 25 | #import "RSCustomTabbarController.h" 26 | #import "RSCustomTabbarController-SWift.h" // this one is for importing swift classes into objective-c 27 | #import "AppDelegate.h" 28 | 29 | #define MENU_ITEM_TITLE_KEY @"menu.item.title" 30 | #define MENU_ITEM_DESCRIPTION_KEY @"menu.item.description" 31 | #define MENU_ITEM_NUMBER_OF_VC @"menu.item.number.of.vc" 32 | #define MENU_ITEM_HANDLER_SELECTOR @"menu.item.selector" 33 | 34 | 35 | @interface MenuTableViewController () 36 | 37 | 38 | @end 39 | 40 | @implementation MenuTableViewController 41 | { 42 | NSArray *menuData; 43 | NSUInteger initialSelectedTabbarIndex; 44 | } 45 | 46 | 47 | - (void)viewDidLoad { 48 | [super viewDidLoad]; 49 | // Do any additional setup after loading the view. 50 | NSString *menuDataFilePath = [[NSBundle mainBundle] pathForResource:@"MenuData" ofType:@"plist"]; 51 | menuData = [NSArray arrayWithContentsOfFile:menuDataFilePath]; 52 | 53 | AppDelegate *appDelegate = [UIApplication sharedApplication].delegate; 54 | [appDelegate setCurrentNavigationController:self.navigationController]; 55 | 56 | // 57 | // for self sizing row 58 | // 59 | self.tableView.rowHeight = UITableViewAutomaticDimension; 60 | self.tableView.estimatedRowHeight = 121; 61 | 62 | self.title = @"Demo List"; 63 | } 64 | 65 | -(void)viewWillAppear:(BOOL)animated 66 | { 67 | [super viewWillAppear:animated]; 68 | self.navigationController.navigationBarHidden = NO; 69 | } 70 | 71 | - (void)didReceiveMemoryWarning { 72 | [super didReceiveMemoryWarning]; 73 | // Dispose of any resources that can be recreated. 74 | } 75 | 76 | /* 77 | #pragma mark - Navigation 78 | 79 | // In a storyboard-based application, you will often want to do a little preparation before navigation 80 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 81 | // Get the new view controller using [segue destinationViewController]. 82 | // Pass the selected object to the new view controller. 83 | } 84 | */ 85 | 86 | 87 | #pragma mark UITableViewDataSource 88 | - (NSInteger)tableView:(UITableView *)tableView 89 | numberOfRowsInSection:(NSInteger)section 90 | { 91 | return menuData.count; 92 | } 93 | 94 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 95 | { 96 | MenuTableCell *customCell = (MenuTableCell*) [tableView dequeueReusableCellWithIdentifier:@"menu_cell"]; 97 | 98 | NSDictionary *singleMenuData = menuData[indexPath.row]; 99 | customCell.titleLabel.text = singleMenuData [MENU_ITEM_TITLE_KEY]; 100 | customCell.descriptionLabel.text = singleMenuData [MENU_ITEM_DESCRIPTION_KEY]; 101 | 102 | NSNumber *numberOfViewController = singleMenuData[MENU_ITEM_NUMBER_OF_VC]; 103 | 104 | // 105 | // kept it 1 indexing 106 | // 107 | customCell.initialViewControllerSelectorStepper.minimumValue = 1; 108 | customCell.initialViewControllerSelectorStepper.maximumValue = numberOfViewController.integerValue; 109 | 110 | customCell.initialViewControllerSelectorStepper.value = 1; 111 | customCell.stepperStatusLabel.text = [NSString stringWithFormat:@"initial vc 1/%ld", (long)numberOfViewController.integerValue]; 112 | 113 | 114 | return customCell; 115 | } 116 | 117 | #pragma mark UITableViewDelegate 118 | - (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath{ 119 | 120 | MenuTableCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 121 | NSUInteger oneIndexedVal = cell.initialViewControllerSelectorStepper.value; 122 | initialSelectedTabbarIndex = oneIndexedVal - 1; 123 | 124 | NSDictionary *menuDataItem = menuData[indexPath.row]; 125 | 126 | NSString *selectorString = menuDataItem[MENU_ITEM_HANDLER_SELECTOR]; 127 | SEL selector = NSSelectorFromString(selectorString); 128 | 129 | 130 | if([self respondsToSelector:selector]) 131 | { 132 | [self performSelector:selector]; 133 | } 134 | else 135 | { 136 | NSLog(@"selector not found in self"); 137 | } 138 | } 139 | 140 | 141 | #pragma mark private helper 142 | -(void)showOnDemo1 143 | { 144 | [self showDemoWithTabbarStoryboardFile:@"demo1" 145 | childViewControllerStoryboardName:@"childs" 146 | childVCSID:@[@"firstVC", 147 | @"secondVC", 148 | @"thirdVC", 149 | @"fourthVC"]]; 150 | } 151 | 152 | -(void)showOnDemo2 153 | { 154 | [self showDemoWithTabbarStoryboardFile:@"demo2" 155 | childViewControllerStoryboardName:@"childs" 156 | childVCSID:@[@"firstVC", 157 | @"secondVC", 158 | @"thirdVC", 159 | @"fourthVC"]]; 160 | } 161 | 162 | -(void)showOnDemo3 163 | { 164 | [self showDemoWithTabbarStoryboardFile:@"demo3" 165 | childViewControllerStoryboardName:@"childs" 166 | childVCSID:@[@"firstVC", 167 | @"secondVC", 168 | @"thirdVC"]]; 169 | } 170 | 171 | -(void)showOnDemo4 172 | { 173 | // 174 | // this is set so that, no default view controller is selected by the next function call 175 | // 176 | initialSelectedTabbarIndex = CUSTOM_TABBAR_INITIAL_VIEWCONTROLLER_INDEX; 177 | 178 | [self showDemoWithTabbarStoryboardFile:@"demo4" 179 | childViewControllerStoryboardName:nil 180 | childVCSID:nil]; 181 | } 182 | 183 | -(void)showOnDemo5 184 | { 185 | [self showDemoWithTabbarStoryboardFile:@"demo5" 186 | childViewControllerStoryboardName:@"demo5" 187 | childVCSID:@[@"firstVC", 188 | @"secondVC", 189 | @"thirdVC", 190 | @"fourthVC"]]; 191 | } 192 | 193 | -(void)showOnDemo6 194 | { 195 | [self showDemoWithTabbarStoryboardFile:@"demo6" 196 | childViewControllerStoryboardName:@"childs" 197 | childVCSID:@[@"firstVC", 198 | @"secondVC", 199 | @"thirdVC", 200 | @"fourthVC"]]; 201 | } 202 | 203 | #pragma mark CustomTabbarDelegate 204 | - (void)customTabbarControllerViewDidLoaded:(RSCustomTabbarControllerBasic *)tabBarController 205 | { 206 | NSLog(@"We are just confirmed that, our default custom tabbar is been loaded"); 207 | } 208 | 209 | #pragma mark private helper method 210 | -(NSArray*)createViewControllerFromStoryboardFile:(NSString*)fileName 211 | viewControllerArr:(NSArray*)viewControllerIDs 212 | { 213 | if(!fileName || fileName.length == 0) 214 | { 215 | return @[]; 216 | } 217 | 218 | UIStoryboard *storyboard = [UIStoryboard storyboardWithName:fileName bundle:[NSBundle mainBundle]]; 219 | NSMutableArray *vcs = [[NSMutableArray alloc] init]; 220 | 221 | for(NSString *viewControllerId in viewControllerIDs) 222 | { 223 | [vcs addObject:[storyboard instantiateViewControllerWithIdentifier:viewControllerId]]; 224 | } 225 | 226 | return [NSArray arrayWithArray:vcs]; 227 | } 228 | 229 | -(void)showDemoWithTabbarStoryboardFile:(NSString*)tabbarStoryboardFile 230 | childViewControllerStoryboardName:(NSString*)childStoryboardName 231 | childVCSID:(NSArray*)childViewControllersID 232 | { 233 | NSArray *childVCs = [self createViewControllerFromStoryboardFile:childStoryboardName 234 | viewControllerArr:childViewControllersID]; 235 | // initiating tabbar controller 236 | UIStoryboard *tabbarStory = [UIStoryboard storyboardWithName:tabbarStoryboardFile bundle:[NSBundle mainBundle]]; 237 | RSCustomTabbarController *tabbarController = [tabbarStory instantiateInitialViewController]; 238 | // setting some implementation 239 | [tabbarController setViewControllers:childVCs]; 240 | tabbarController.implementationDelegate = (id)tabbarController; 241 | tabbarController.delegate = self; 242 | // hiding the navigation controller 243 | self.navigationController.navigationBarHidden = YES; 244 | 245 | // 246 | // in the app delegate set the tabbar controller as the 247 | // currently working tabbar controller 248 | // 249 | AppDelegate *appDelegate = [UIApplication sharedApplication].delegate; 250 | [appDelegate setCurrentCustomTabbarController:tabbarController]; 251 | 252 | if(initialSelectedTabbarIndex != CUSTOM_TABBAR_INITIAL_VIEWCONTROLLER_INDEX) 253 | { 254 | // 255 | // make a pending block which will 256 | // select the initial selected view controller 257 | // 258 | RSCustomTabbarPendingBlock pendingBlock = ^{ 259 | [tabbarController setSelectedViewCotnrollerAtIndex:initialSelectedTabbarIndex]; 260 | }; 261 | 262 | 263 | // do it manually 264 | if(![tabbarController isViewLoaded]) 265 | { 266 | // 267 | // view of the tabbar is not loaded yet 268 | // so just add a pending block 269 | // 270 | [tabbarController setShouldSelectDefaultViewController:NO]; 271 | [tabbarController addPendingBlockIntendedToBeExecutedAfterViewDidLoad:pendingBlock]; 272 | 273 | } 274 | else 275 | { 276 | // 277 | // view of the tabbar is already loaded 278 | // so execute the pending block by yourself 279 | // 280 | // this case is not gonna be occur, unless you 281 | // cache the tabbar controller or used it more than once 282 | // 283 | pendingBlock(); 284 | } 285 | } 286 | else 287 | { 288 | // just let it go :P 289 | [tabbarController setShouldSelectDefaultViewController:YES]; 290 | } 291 | 292 | [self.navigationController pushViewController:tabbarController animated:YES]; 293 | } 294 | @end 295 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Demo4/Demo4TabbarController.m: -------------------------------------------------------------------------------- 1 | // 2 | // Demo4TabbarController.m 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 10/8/16. 6 | // Copyright © 2016 funtoos. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 9 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 12 | // following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in all copies or substantial 15 | // portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 18 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 19 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 21 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import "Demo4TabbarController.h" 24 | #import "Demo4TabbarCell.h" 25 | #import "BrowserChildVC.h" 26 | #import "AppDelegate.h" 27 | #import "FadingTabbarTransitionAnimation.h" 28 | 29 | #define TABBAR_CELL_REUSE_ID @"tabbar.reuse.cell.id" 30 | // 31 | // used in info dictionary 32 | // 33 | #define TABBAR_CELL_LABEL_KEY @"tabbar.label.key" 34 | #define TABBAR_CELL_SELECTED_KEY @"tabbar.selected.key" 35 | 36 | #define TABBAR_MIN_WIDTH 65 37 | #define TABBAR_MAX_WIDTH 90 38 | 39 | typedef void(^collectionViewConstraintUpdated)(); 40 | 41 | @interface Demo4TabbarController () < UICollectionViewDataSource, 42 | UICollectionViewDelegateFlowLayout, 43 | Demo4TabbarCellDelegate> 44 | { 45 | NSMutableArray *tabbarsInfo; 46 | NSMutableArray *mutableViewControllers; 47 | 48 | UIStoryboard *broswerStoryboard; 49 | } 50 | 51 | @property (strong, nonatomic) IBOutlet UIButton *mViewAddBtn; 52 | @property (strong, nonatomic) IBOutlet UICollectionView *mViewTabbarCollectionView; 53 | @property (strong, nonatomic) IBOutlet NSLayoutConstraint *mViewCollectionViewWidth; 54 | 55 | @end 56 | 57 | @implementation Demo4TabbarController 58 | 59 | - (void)viewDidLoad { 60 | tabbarsInfo = [[NSMutableArray alloc] init]; 61 | mutableViewControllers = [[NSMutableArray alloc] init]; 62 | 63 | _mViewTabbarCollectionView.allowsSelection = YES; 64 | _mViewTabbarCollectionView.allowsMultipleSelection = NO; 65 | 66 | broswerStoryboard = [UIStoryboard storyboardWithName:@"childs" bundle:[NSBundle mainBundle]]; 67 | 68 | _mViewAddBtn.imageView.contentMode = UIViewContentModeScaleAspectFit; 69 | super.transitionAnimationDelegate = [[FadingTabbarTransitionAnimation alloc] init]; 70 | 71 | [super viewDidLoad]; 72 | } 73 | 74 | -(void)viewDidLayoutSubviews 75 | { 76 | [super viewDidLayoutSubviews]; 77 | 78 | // 79 | // set the collection view's layout here 80 | // 81 | UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout*)_mViewTabbarCollectionView.collectionViewLayout; 82 | _mViewTabbarCollectionView.contentInset = UIEdgeInsetsZero; 83 | 84 | layout.sectionInset = UIEdgeInsetsZero; 85 | layout.minimumLineSpacing = 0.0; 86 | layout.minimumInteritemSpacing = 0.0; 87 | layout.headerReferenceSize = CGSizeZero; 88 | layout.footerReferenceSize = CGSizeZero; 89 | 90 | _mViewTabbarCollectionView.collectionViewLayout = layout; 91 | } 92 | 93 | -(void)viewWillAppear:(BOOL)animated 94 | { 95 | [super viewWillAppear:animated]; 96 | [self.view layoutIfNeeded]; 97 | } 98 | 99 | - (void)didReceiveMemoryWarning { 100 | [super didReceiveMemoryWarning]; 101 | // Dispose of any resources that can be recreated. 102 | } 103 | 104 | /* 105 | #pragma mark - Navigation 106 | 107 | // In a storyboard-based application, you will often want to do a little preparation before navigation 108 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 109 | // Get the new view controller using [segue destinationViewController]. 110 | // Pass the selected object to the new view controller. 111 | } 112 | */ 113 | 114 | 115 | #pragma mark IBActions 116 | - (IBAction)onAddActionBtnPressed:(id)sender 117 | { 118 | 119 | NSInteger count = tabbarsInfo.count; 120 | [tabbarsInfo addObject:[[NSMutableDictionary alloc] initWithDictionary:@{TABBAR_CELL_LABEL_KEY : [NSNumber numberWithInteger:count], 121 | TABBAR_CELL_SELECTED_KEY : [NSNumber numberWithBool:YES]}]]; 122 | 123 | BrowserChildVC *browserVC = [broswerStoryboard instantiateViewControllerWithIdentifier:@"browser_child_vc"]; 124 | [mutableViewControllers addObject:browserVC]; 125 | [super setViewControllers:mutableViewControllers]; 126 | 127 | 128 | [self refreshCollectionViewSize:^{ 129 | NSIndexPath *newItemIndexPath = [NSIndexPath indexPathForRow:tabbarsInfo.count-1 inSection:0]; 130 | [_mViewTabbarCollectionView insertItemsAtIndexPaths:@[newItemIndexPath]]; 131 | [_mViewTabbarCollectionView scrollToItemAtIndexPath:newItemIndexPath atScrollPosition:UICollectionViewScrollPositionRight animated:YES]; 132 | [super setSelectedViewCotnrollerAtIndex:newItemIndexPath.row]; 133 | }]; 134 | } 135 | 136 | - (IBAction)onBackPressed:(id)sender 137 | { 138 | [AppDelegate moveToMenuTableViewController]; 139 | } 140 | 141 | 142 | 143 | 144 | #pragma mark RSCustomTabbarImplementationDelegate 145 | -(CGFloat)heightForTabbarController:(RSCustomTabbarController*)tabbarController 146 | { 147 | return 38; 148 | } 149 | -(void)newSelectedTabbarIndex:(NSUInteger)newSelectedIndex whereOldIndexWas:(NSUInteger)oldSelectedIndex 150 | { 151 | if(newSelectedIndex == oldSelectedIndex) 152 | { 153 | //it's for the first item 154 | NSIndexPath *selectedIndexPath = [NSIndexPath indexPathForRow:newSelectedIndex inSection:0]; 155 | [self selectCellAtIndexPath:selectedIndexPath forCollectionView:_mViewTabbarCollectionView]; 156 | } 157 | else 158 | { 159 | 160 | NSLog(@"selected %ld unselected %ld", newSelectedIndex, oldSelectedIndex); 161 | 162 | //subsequent calls 163 | NSIndexPath *unselectedIndexPath = [NSIndexPath indexPathForRow:oldSelectedIndex inSection:0]; 164 | NSIndexPath *selectedIndexPath = [NSIndexPath indexPathForRow:newSelectedIndex inSection:0]; 165 | 166 | [self selectCellAtIndexPath:selectedIndexPath forCollectionView:_mViewTabbarCollectionView]; 167 | [self unselectCellAtIndexPath:unselectedIndexPath forCollectionView:_mViewTabbarCollectionView]; 168 | } 169 | } 170 | 171 | 172 | #pragma mark UICollectionViewDataSource 173 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section 174 | { 175 | return tabbarsInfo.count; 176 | } 177 | 178 | // The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath: 179 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 180 | { 181 | Demo4TabbarCell *cell = (Demo4TabbarCell*)[collectionView dequeueReusableCellWithReuseIdentifier:TABBAR_CELL_REUSE_ID 182 | forIndexPath:indexPath]; 183 | NSDictionary *tabbarInfo = tabbarsInfo[indexPath.row]; 184 | NSNumber *number = tabbarInfo[TABBAR_CELL_LABEL_KEY]; 185 | NSNumber *isSelected = tabbarInfo[TABBAR_CELL_SELECTED_KEY]; 186 | 187 | cell.mViewLabel.text = [NSString stringWithFormat:@"%ld", number.integerValue]; 188 | [cell setNormalOrSelectedImage:[isSelected boolValue]]; 189 | 190 | cell.delegate = self; 191 | return cell; 192 | } 193 | 194 | #pragma mark UICollectionViewDelegate 195 | -(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath 196 | { 197 | [super setViewControllers:mutableViewControllers]; 198 | [super setSelectedViewCotnrollerAtIndex:indexPath.row]; 199 | } 200 | 201 | #pragma mark UICollectionViewFlowLayoutDelegate 202 | - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath 203 | { 204 | 205 | CGFloat perItemWidth = collectionView.bounds.size.width / tabbarsInfo.count; 206 | 207 | if(perItemWidth > TABBAR_MAX_WIDTH) 208 | { 209 | perItemWidth = TABBAR_MAX_WIDTH; 210 | } 211 | 212 | if(perItemWidth < TABBAR_MIN_WIDTH) 213 | { 214 | perItemWidth = TABBAR_MIN_WIDTH; 215 | } 216 | 217 | return CGSizeMake(perItemWidth, 218 | collectionView.bounds.size.height); 219 | } 220 | 221 | 222 | #pragma mark Demo4TabbarCellDelegate 223 | -(void)crossPressedForDemo4TabbarCell:(Demo4TabbarCell*)cell 224 | { 225 | NSIndexPath *indexPath = [_mViewTabbarCollectionView indexPathForCell:cell]; 226 | NSInteger index = indexPath.row; 227 | 228 | [_mViewTabbarCollectionView scrollToItemAtIndexPath:indexPath 229 | atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally 230 | animated:YES]; 231 | 232 | UIViewController *targetViewController = mutableViewControllers[index]; 233 | [super removeViewControllerFromContainer:targetViewController]; 234 | 235 | [mutableViewControllers removeObjectAtIndex:index]; 236 | [tabbarsInfo removeObjectAtIndex:index]; 237 | [_mViewTabbarCollectionView deleteItemsAtIndexPaths:@[indexPath]]; 238 | 239 | [super setViewControllers:mutableViewControllers]; 240 | 241 | [self refreshCollectionViewSize:nil]; 242 | } 243 | 244 | 245 | #pragma mark private methods 246 | -(void)selectCellAtIndexPath:(NSIndexPath*)indexPath forCollectionView:(UICollectionView*)collectionView 247 | { 248 | // 249 | // change the data to selected 250 | // 251 | [self selectUnselectTabbarInCollectionView:collectionView AtIndexPath:indexPath isSelected:YES]; 252 | } 253 | 254 | -(void)unselectCellAtIndexPath:(NSIndexPath*)indexPath forCollectionView:(UICollectionView*)collectionView 255 | { 256 | // 257 | // change the data to selected 258 | // 259 | [self selectUnselectTabbarInCollectionView:collectionView 260 | AtIndexPath:indexPath 261 | isSelected:NO]; 262 | } 263 | 264 | -(void)refreshCollectionViewSize:(collectionViewConstraintUpdated)completion 265 | { 266 | _mViewCollectionViewWidth.constant = tabbarsInfo.count * TABBAR_MAX_WIDTH; 267 | 268 | [self.view updateConstraints]; 269 | [UIView animateWithDuration:0.3 animations:^{ 270 | [self.view layoutIfNeeded]; 271 | 272 | } completion:^(BOOL finished) { 273 | if(completion) 274 | completion(); 275 | }]; 276 | } 277 | 278 | #pragma mark private helper method 279 | -(void)selectUnselectTabbarInCollectionView:(UICollectionView*)collectionView 280 | AtIndexPath:(NSIndexPath*)indexPath 281 | isSelected:(BOOL)isSelected 282 | { 283 | // 284 | // change the data to selected 285 | // 286 | NSMutableDictionary *tabbarInfo = tabbarsInfo[indexPath.row]; 287 | tabbarInfo[TABBAR_CELL_SELECTED_KEY] = [NSNumber numberWithBool:isSelected]; 288 | 289 | Demo4TabbarCell *cell = (Demo4TabbarCell*)[collectionView cellForItemAtIndexPath:indexPath]; 290 | [cell setNormalOrSelectedImage:isSelected]; 291 | } 292 | 293 | @end 294 | -------------------------------------------------------------------------------- /RSCustomTabbarController/CustomTabbarConroller/RSCustomTabbarControllerBasic.m: -------------------------------------------------------------------------------- 1 | // 2 | // RSCustomTabbarControllerBasic.m 3 | // RSCustomTabbarController 4 | // 5 | // Created by Ratul Sharker on 11/6/16. 6 | // Copyright © 2016 funtoos. All rights reserved. 7 | // 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 10 | // associated documentation files (the "Software"), to deal in the Software without restriction, including 11 | // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 13 | // following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all copies or substantial 16 | // portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 19 | // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 20 | // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 22 | // THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | 25 | #import "RSCustomTabbarControllerBasic.h" 26 | 27 | @interface RSCustomTabbarControllerBasic () 28 | { 29 | 30 | BOOL shouldLoadDefaultViewController; 31 | } 32 | @end 33 | 34 | @implementation RSCustomTabbarControllerBasic 35 | 36 | - (void)viewDidLoad { 37 | [super viewDidLoad]; 38 | 39 | selectedIndex = DEFAULT_SELECTED_INDEX_WHILE_NOTHING_ON_CONTAINER; 40 | 41 | if(shouldLoadDefaultViewController) 42 | { 43 | selectedIndex = CUSTOM_TABBAR_INITIAL_VIEWCONTROLLER_INDEX; 44 | [self setSelectedViewCotnrollerAtIndex:selectedIndex]; 45 | } 46 | else 47 | { 48 | NSLog(@"default view controller is not loaded"); 49 | } 50 | 51 | [self callDelegateViewDidLoadedWithTarget:self.delegate]; 52 | } 53 | 54 | 55 | 56 | 57 | #pragma mark basic public functionality 58 | -(void)setShouldSelectDefaultViewController:(BOOL)shouldSelect 59 | { 60 | shouldLoadDefaultViewController = shouldSelect; 61 | } 62 | 63 | -(void)setViewControllers:(NSArray*)vcs 64 | { 65 | viewControllers = vcs; 66 | 67 | selectedIndex = DEFAULT_SELECTED_INDEX_WHILE_NOTHING_ON_CONTAINER; 68 | 69 | // 70 | // now lookup for the child view controller 71 | // any of them are in viewcontorllers, if it is 72 | // then update the currently selected according to 73 | // that. 74 | // 75 | for(NSUInteger index = 0; index < viewControllers.count; index++) 76 | { 77 | if(viewControllers[index].parentViewController == self) 78 | { 79 | selectedIndex = index; 80 | break; 81 | } 82 | } 83 | } 84 | 85 | -(void)setSelectedViewCotnrollerAtIndex:(NSUInteger)index 86 | { 87 | if(viewControllers && index < viewControllers.count /*&& index != selectedIndex*/) 88 | { 89 | 90 | if(selectedIndex == DEFAULT_SELECTED_INDEX_WHILE_NOTHING_ON_CONTAINER) 91 | { 92 | // 93 | // first time experience 94 | // 95 | selectedIndex = index; 96 | } 97 | 98 | // 99 | // appropriate time for calling the tabbar 100 | // button state update 101 | // 102 | if(self.implementationDelegate && 103 | [self.implementationDelegate respondsToSelector:@selector(newSelectedTabbarIndex: 104 | whereOldIndexWas:)]) 105 | { 106 | [self.implementationDelegate newSelectedTabbarIndex:index 107 | whereOldIndexWas:selectedIndex]; 108 | } 109 | else 110 | { 111 | RSCT_ERROR(@"RSCustomTabbarController implementation delegate is not properly implemented, actually the selector 💔 newSelectedTabbarIndex:whereOldIndexWas: 💔 is not found"); 112 | } 113 | 114 | [self manageViewControllerToBeInFrontContainer:index]; 115 | } 116 | else 117 | { 118 | NSLog(@"index is too much high to be set %ld", (long)selectedIndex); 119 | } 120 | } 121 | 122 | -(void)setTabbarVisibility:(BOOL)visible animated:(BOOL)animated 123 | { 124 | // 125 | // assume here tabbar default height never changing thing 126 | // 127 | if(self.implementationDelegate && 128 | [self.implementationDelegate respondsToSelector:@selector(heightForTabbarController:)]) 129 | { 130 | CGFloat height = [self.implementationDelegate heightForTabbarController:self]; 131 | for(NSLayoutConstraint *constraint in self.implementationDelegate.tabbarContainerHeight) 132 | { 133 | constraint.constant = visible * height; 134 | } 135 | 136 | for(NSLayoutConstraint *constraint in self.implementationDelegate.tabbarWidgetHolderTop) 137 | { 138 | constraint.active = visible; 139 | } 140 | 141 | // 142 | // do the animation if needed to 143 | // 144 | if(animated) 145 | { 146 | [self animateConstraintChangesWithDuration:0.5]; 147 | } 148 | } 149 | else 150 | { 151 | RSCT_ERROR(@"RSCustomTabbarController implementation delegate is not properly implemented, actually the selector 💔 heightForTabbarController: 💔 not found"); 152 | } 153 | } 154 | 155 | -(UIViewController *)getViewControllerAtIndex:(NSUInteger)index 156 | { 157 | if(viewControllers && index < viewControllers.count) 158 | { 159 | return [viewControllers objectAtIndex:index]; 160 | } 161 | else 162 | { 163 | return nil; 164 | } 165 | } 166 | 167 | -(UIViewController *)getSelectedViewController 168 | { 169 | return [self getViewControllerAtIndex:selectedIndex]; 170 | } 171 | 172 | -(NSInteger)getSelectedIndex 173 | { 174 | if(viewControllers) 175 | { 176 | return selectedIndex; 177 | } 178 | else 179 | { 180 | return -1; 181 | } 182 | } 183 | 184 | #pragma mark private functionality 185 | -(void)manageViewControllerToBeInFrontContainer:(NSUInteger)index 186 | { 187 | UIViewController *targetViewController = [self checkTheViewControllerAtIndexForManaging:index]; 188 | 189 | if(targetViewController) 190 | { 191 | // 192 | // adding the new view controller 193 | // 194 | [self addViewControllerAndView:targetViewController]; 195 | 196 | NSMutableSet *previousViewControllers = [[NSMutableSet alloc] initWithArray:self.childViewControllers]; 197 | [previousViewControllers removeObject:targetViewController]; 198 | 199 | // 200 | // forming the completion block 201 | // 202 | RSCustomTabbarGeneralPurposeBlock completionBlock = ^{ 203 | // though at a time only one child viewcontroller 204 | // will be in existence, but we should remove all 205 | // for sake of generality 206 | for(UIViewController *childVC in previousViewControllers) 207 | { 208 | [childVC willMoveToParentViewController:nil]; 209 | [childVC.view removeFromSuperview]; 210 | [childVC removeFromParentViewController]; 211 | } 212 | 213 | // 214 | // store the new selected index, for later use and consistency 215 | // 216 | selectedIndex = index; 217 | 218 | // 219 | // for surity 220 | // 221 | if(self.implementationDelegate && self.implementationDelegate.viewControllerContainer) 222 | { 223 | targetViewController.view.frame = self.implementationDelegate.viewControllerContainer.bounds; 224 | } 225 | else 226 | { 227 | RSCT_ERROR(@"RSCustomTabbarController implementation delegate is not properly implemented, actually the property 💔 viewControllerContainer 💔 not found"); 228 | } 229 | 230 | 231 | // 232 | // call the lifecycle viewControllerDidAppear 233 | // 234 | [self callViewControllerDidAppearAnimationFinishedIn:targetViewController 235 | atIndex:index]; 236 | 237 | }; 238 | 239 | 240 | // 241 | // if transition animation exists, call it, otherwise call the completion block 242 | // 243 | if(![self callTransitionAnimationDelegateWillSwitchFrom:selectedIndex 244 | willSwitchTo:index 245 | withCompletionBlock:completionBlock]) 246 | { 247 | completionBlock(); 248 | } 249 | } 250 | else 251 | { 252 | NSLog(@"TOO MUCH TAG VALUE IS SET, WHICH IS OUT OF THE NUMBE OF THE VIEWCONTROLLERS"); 253 | } 254 | } 255 | -(UIViewController*)checkTheViewControllerAtIndexForManaging:(NSUInteger)index 256 | { 257 | if(viewControllers && viewControllers.count > index) 258 | { 259 | // 260 | // -previous implementation. 261 | // if the view controller isn't already a child, then 262 | // add it to the child view controller. otherwise nothing to do 263 | // first of all check that is this viewController's view is in the container view 264 | // 265 | //return (viewControllers[index].parentViewController == self) ? nil : viewControllers[index]; 266 | 267 | // 268 | // -policy changes 269 | // if a view controller is already a child in the RSCustomTabbarController 270 | // in this case previously no further action was taken. But from this 271 | // revision, if there any view controller within the viewControllers array, 272 | // will be readed and their containment cycle will be re-enumerated. 273 | // 274 | // -reason behind doing this. 275 | // some developer may want to add same view controller but upon tab changes 276 | // they want the whole containment cycle will be enumerated and the view controller 277 | // will be notified of that index changes. To support this scenario this policy changes 278 | // are done. 279 | // 280 | // NB:: beware doing any animation with setting same view controller instance in 281 | // multiple tabbar. in that case, you may ending up in a situation like treating 282 | // the same view controller as the previously selected view controller and new selected 283 | // view controller. This sort of animation can't be supported in any such criteria. 284 | // 285 | // 286 | return viewControllers[index]; 287 | } 288 | else 289 | { 290 | return nil; 291 | } 292 | } 293 | 294 | -(void)addViewControllerAndView:(UIViewController*)targetViewController 295 | { 296 | if(self.implementationDelegate && self.implementationDelegate.viewControllerContainer) 297 | { 298 | [self addChildViewController:targetViewController]; 299 | [self.implementationDelegate.viewControllerContainer addSubview:targetViewController.view]; 300 | targetViewController.view.frame = self.implementationDelegate.viewControllerContainer.bounds; 301 | [targetViewController.view setNeedsLayout]; 302 | [targetViewController.view layoutIfNeeded]; 303 | [targetViewController didMoveToParentViewController:self]; 304 | } 305 | else 306 | { 307 | RSCT_ERROR(@"RSCustomTabbarController implementation delegate not properly implemented, actually the property 💔 viewControllerContainer 💔 not found"); 308 | } 309 | 310 | } 311 | -(BOOL)callTransitionAnimationDelegateWillSwitchFrom:(NSUInteger)oldIndex 312 | willSwitchTo:(NSUInteger)newIndex 313 | withCompletionBlock:(RSCustomTabbarGeneralPurposeBlock)completionBlock 314 | { 315 | if(self.transitionAnimationDelegate && 316 | [self.transitionAnimationDelegate respondsToSelector:@selector(customTabbarController: 317 | willSwitchFromIndex: 318 | willSwitchToIndex: 319 | withAnimationCompletionBlock:)]) 320 | { 321 | [self.transitionAnimationDelegate customTabbarController:self 322 | willSwitchFromIndex:oldIndex 323 | willSwitchToIndex:newIndex 324 | withAnimationCompletionBlock:completionBlock]; 325 | 326 | return YES; 327 | } 328 | else 329 | { 330 | return NO; 331 | } 332 | } 333 | 334 | 335 | -(void)callDelegateViewDidLoadedWithTarget:(id)target 336 | { 337 | if(target && [target respondsToSelector:@selector(customTabbarControllerViewDidLoaded:)]) 338 | { 339 | [target customTabbarControllerViewDidLoaded:self]; 340 | } 341 | else 342 | { 343 | NSLog(@"RSCustomTabbarController view did load delegate not implemented"); 344 | } 345 | } 346 | 347 | -(void)callViewControllerDidAppearAnimationFinishedIn:(UIViewController*)targetViewController 348 | atIndex:(NSUInteger)index 349 | { 350 | id justAddedVC = (id)targetViewController; 351 | 352 | if([justAddedVC respondsToSelector:@selector(viewControllerDidAppearAnimationFinishedInTabbar: 353 | atIndex:)]) 354 | { 355 | [justAddedVC viewControllerDidAppearAnimationFinishedInTabbar:self 356 | atIndex:index]; 357 | } 358 | else 359 | { 360 | NSLog(@"LIFE Cycle callback not implemented"); 361 | } 362 | } 363 | 364 | -(void)animateConstraintChangesWithDuration:(NSTimeInterval)timeInterval 365 | { 366 | [UIView animateWithDuration:timeInterval 367 | animations:^{ 368 | 369 | [self.view layoutIfNeeded]; 370 | 371 | } completion:^(BOOL finished) { 372 | [[UIApplication sharedApplication] endIgnoringInteractionEvents]; 373 | }]; 374 | } 375 | @end 376 | -------------------------------------------------------------------------------- /RSCustomTabbarController/Demo1/demo1.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 45 | 57 | 69 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | --------------------------------------------------------------------------------