How can I set another ViewController for the searchResultsUpdater?
I tried to do it like this, but the results are not updating.
let searchNav = storyboard!.instantiateViewController(withIdentifier: "SearchControllerNav") as! UINavigationController
let vc = searchNav.topViewController as! PageMenuVC
let searchVC = storyboard!.instantiateViewController(withIdentifier: "SearchVC") as! SearchVC
self.searchController = UISearchController(searchResultsController: vc)
vc.searchController.searchResultsUpdater = searchVC
Here's my PageMenuVC:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
var controllerArray : [UIViewController] = []
let searchVC = storyboard?.instantiateViewController(withIdentifier: "SearchVC")
controllerArray.append(searchVC!)
let testVC = storyboard?.instantiateViewController(withIdentifier: "test")
controllerArray.append(testVC!)
// Customize menu (Optional)
let parameters: [CAPSPageMenuOption] = [
.scrollMenuBackgroundColor(UIColor(red: 30.0/255.0, green: 30.0/255.0, blue: 30.0/255.0, alpha: 1.0)),
.viewBackgroundColor(UIColor(red: 20.0/255.0, green: 20.0/255.0, blue: 20.0/255.0, alpha: 1.0)),
.selectionIndicatorColor(UIColor.orange),
.bottomMenuHairlineColor(UIColor(red: 70.0/255.0, green: 70.0/255.0, blue: 80.0/255.0, alpha: 1.0)),
.menuItemFont(UIFont(name: "HelveticaNeue", size: 13.0)!),
.menuHeight(40.0),
.menuItemWidth(90.0),
.centerMenuItems(true)
]
// Initialize scroll menu
pageMenu = CAPSPageMenu(viewControllers: controllerArray, frame: CGRect(x: 0.0, y: 0.0, width: self.view.frame.width, height: self.view.frame.height), pageMenuOptions: nil)
self.addChildViewController(pageMenu!)
self.view.addSubview(pageMenu!.view)
pageMenu!.didMove(toParentViewController: self)
}
In SearchVC I have this function:
//MARK: Filter
func filterContentForSearchText(searchText: String, scope: String = "All") {
filteredUsers = allUsers.filter { user in
return user.name.lowercased().contains(searchText.lowercased())
}
collectionView.reloadData()
}
//MARK: SearchResultDelegate
func updateSearchResults(for searchController: UISearchController) {
let searchBarText = searchController.searchBar.text!
filterContentForSearchText(searchText: searchBarText)
self.searchController = searchController
collectionView.reloadData()
}
If you need more info, let me know!
I think you need to keep the instantiated view controllers in a (private) property of the self view controller: If you set it as the the delegate to vc.searchController.searchResultsUpdater, this is only a weak reference, therefore if you do not store searchVC in self, it will be destroyed too soon (just at the end of the code block). The same holds for searchNav (but I think this will be presented, therefore I'll skip it below):
class MyVC : UIViewController {
var searchVC:UIViewController?
// ...
func XYZ() {
let searchNav = storyboard!.instantiateViewController(withIdentifier: "SearchControllerNav") as! UINavigationController
let vc = searchNav.topViewController as! PageMenuVC
// Store searchVC in property:
self.searchVC = storyboard!.instantiateViewController(withIdentifier: "SearchVC") as! SearchVC
self.searchController = UISearchController(searchResultsController: vc)
vc.searchController.searchResultsUpdater = searchVC
self.present(searchNav, animated:true, completion:nil)
}
}
Related
How to make for Pageviewcontroller background transparent,
I am trying here to make it transparent
super.viewDidLoad()
self.pageviewcontroller = self.storyboard?.instantiateViewController(withIdentifier: "PageViewController") as! UIPageViewController
self.pageviewcontroller.dataSource = self
self.pageviewcontroller.delegate = self
var pageControl = UIPageControl()
pageControl = UIPageControl.appearance()
pageControl.backgroundColor = .clear
pageControl.pageIndicatorTintColor = .gray
pageControl.currentPageIndicatorTintColor = UIColor(red: 0.00, green: 1.0, blue: 1.0, alpha: 1.0)
pageControl.backgroundColor = UIColor.clear
ViewControllers.append(
UIStoryboard(name: "Main", bundle: nil) .
instantiateViewController(withIdentifier: "DashboardViewController") as! BaseViewController)
ViewControllers.append(
UIStoryboard(name: "Main", bundle: nil) .
instantiateViewController(withIdentifier: "qwertyViewController") as! BaseViewController)
if let firstViewController = ViewControllers.first {
I've tested the following code and it works
This is my controller class:
class PageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
In that class I've created this variable:
lazy var pageArra: [UIViewController] = {
return[self.VCInstance("ONE"),self.VCInstance("TWO"),self.VCInstance("THREE"),self.VCInstance("FOUR")]
}()
Which uses this function to get the storyboard assets. I gave 4 ViewControllers the ID's listed above
private func VCInstance(_ name: String) -> UIViewController {
return UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: name)
}
This is my viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
dataSource = self
delegate = self
var pageControl = UIPageControl()
pageControl = UIPageControl.appearance()
pageControl.pageIndicatorTintColor = .gray
pageControl.currentPageIndicatorTintColor = UIColor(red: 0.00, green: 1.0, blue: 1.0, alpha: 1.0)
}
And This is how I get it to clear when it loads
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if view is UIScrollView {
view.frame = UIScreen.main.bounds
} else if view is UIPageControl {
view.backgroundColor = .clear
}
}
Plus all of the datasource and delegate required methods
I am having that issue when I using PageMenu Framework and put all code for the PageMenu but its showing white space in my controller. Anybody have the solutions for that type of issue.let me know how can I remove it.
Blow I put complete code for PageMenu
import UIKit
import PageMenu
class TradingHistoryVC: UIViewController {
#IBOutlet weak var pagerView: UIView!
var controllerArray : [UIViewController] = []
var pageMenu : CAPSPageMenu?
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.topItem?.title = ""
// Do any additional setup after loading the view.
}
override func viewDidAppear(_ animated: Bool) {
pager()
}
func pager()
{
let buy = storyboard?.instantiateViewController(withIdentifier: "TradingSuccessfullyVCSID") as! TradingSuccessfullyVC
buy.parentNavigationController = navigationController!
buy.title = "Trading Successfully"
controllerArray.append(buy)
let sell = storyboard?.instantiateViewController(withIdentifier: "GlobalTradingVCSID") as! GlobalTradingVC
sell.parentNavigationController = navigationController!
sell.title = "Global Trading"
controllerArray.append(sell)
// Customize menu (Optional)
let parameters: [CAPSPageMenuOption] = [
.scrollMenuBackgroundColor(UIColor(red: 72/255.0, green: 175/255.0, blue: 230/255.0, alpha: 1.0)),
.viewBackgroundColor(UIColor(red: 255.0/255.0, green: 255.0/255.0, blue: 255.0/255.0, alpha: 1.0)),
.selectionIndicatorColor(UIColor(red: 255/255, green: 255/255, blue: 255/255, alpha: 1.0)),
.addBottomMenuHairline(false),
.menuItemFont(UIFont(name: "Times New Roman", size: 16)!),
.menuItemWidth((self.pagerView.frame.width-30)/2),
.menuHeight(50.0),
.enableHorizontalBounce(true),
.menuItemWidthBasedOnTitleTextWidth(false),
.selectedMenuItemLabelColor(UIColor.white),
.unselectedMenuItemLabelColor(UIColor.white),
.menuItemSeparatorWidth(4.5),
.useMenuLikeSegmentedControl(false),
.menuItemSeparatorRoundEdges(true),
.selectionIndicatorHeight(2.0),
.menuItemSeparatorPercentageHeight(0.0),
]
// Initialize scroll menu
pageMenu = CAPSPageMenu(viewControllers: controllerArray, frame: CGRect(x: 0.0, y: 0.0, width: self.pagerView.frame.width, height: self.pagerView.frame.height), pageMenuOptions: parameters)
self.pagerView.addSubview(pageMenu!.view)
// End Pagemenu
}
#IBAction func btnMenuAction(_ sender: Any) {
toggleSideMenuView()
}
}
If anyone have its solutions plz. Please Help to solve it.
I have taken a view controller & embedded it in a navigation Controller and again this has been embedded in a tab bar controller. when I am trying to set a image via story board, the image does not appear on a tab bar icon. Here image name is 25.
What can I do? How can I do it programmatically? what should I take proper image size for this purpose?
In your MainTabbarViewController
Bind the outlet of your tabbar:
#IBOutlet weak var myTabBar: UITabBar?
override func viewDidLoad() {
super.viewDidLoad()
myTabBar?.tintColor = UIColor.white
tabBarItem.title = ""
setTabBarItems()
}
set the tabbar items here defined method below:
func setTabBarItems(){
let myTabBarItem1 = (self.tabBar.items?[0])! as UITabBarItem
myTabBarItem1.image = UIImage(named: "Unselected")?.withRenderingMode(UIImage.RenderingMode.alwaysOriginal)
myTabBarItem1.selectedImage = UIImage(named: "Selected ")?.withRenderingMode(UIImage.RenderingMode.alwaysOriginal)
myTabBarItem1.title = ""
myTabBarItem1.imageInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0)
let myTabBarItem2 = (self.tabBar.items?[1])! as UITabBarItem
myTabBarItem2.image = UIImage(named: "Unselected")?.withRenderingMode(UIImage.RenderingMode.alwaysOriginal)
myTabBarItem2.selectedImage = UIImage(named: "Selected")?.withRenderingMode(UIImage.RenderingMode.alwaysOriginal)
myTabBarItem2.title = ""
myTabBarItem2.imageInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0)
let myTabBarItem3 = (self.tabBar.items?[2])! as UITabBarItem
myTabBarItem3.image = UIImage(named: "Unselected")?.withRenderingMode(UIImage.RenderingMode.alwaysOriginal)
myTabBarItem3.selectedImage = UIImage(named: "Selected")?.withRenderingMode(UIImage.RenderingMode.alwaysOriginal)
myTabBarItem3.title = ""
myTabBarItem3.imageInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0)
let myTabBarItem4 = (self.tabBar.items?[3])! as UITabBarItem
myTabBarItem4.image = UIImage(named: "Unselected")?.withRenderingMode(UIImage.RenderingMode.alwaysOriginal)
myTabBarItem4.selectedImage = UIImage(named: "Selected")?.withRenderingMode(UIImage.RenderingMode.alwaysOriginal)
myTabBarItem4.title = ""
myTabBarItem4.imageInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0)
}
add AppDelegate class :
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
{
window=UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = setTabbar()
self.window?.makeKeyAndVisible()
window?.backgroundColor=UIColor.white
return true
}
func setTabbar() -> UITabBarController
{
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let tabbarcntrl = UITabBarController()
let Home = storyboard.instantiateViewController(withIdentifier: "HomeView") // 1st tab bar viewcontroller
let Followed = storyboard.instantiateViewController(withIdentifier: "FollowedView") // 2nd tab bar viewcontroller
let Message = storyboard.instantiateViewController(withIdentifier: "MessageView") // 3rd tab bar viewcontroller
// all viewcontroller embedded navigationbar
let nvHome = UINavigationController(rootViewController: Home)
let nvFollowed = UINavigationController(rootViewController: Followed)
let nvMessage = UINavigationController(rootViewController: Message)
// all viewcontroller navigationbar hidden
nvHome.setNavigationBarHidden(true, animated: false)
nvFollowed.setNavigationBarHidden(true, animated: false)
nvMessage.setNavigationBarHidden(true, animated: false)
tabbarcntrl.viewControllers = [nvHome,nvFollowed,nvMessage]
let tabbar = tabbarcntrl.tabBar
tabbar.barTintColor = UIColor.black
tabbar.backgroundColor = UIColor.black
tabbar.tintColor = UIColor(red: 43/255, green: 180/255, blue: 0/255, alpha: 1)
//UITabBar.appearance().tintColor = UIColor.white
let attributes = [NSFontAttributeName:UIFont(name: "Montserrat-Light", size: 10)!,NSForegroundColorAttributeName:UIColor.white]
let attributes1 = [NSFontAttributeName:UIFont(name: "Montserrat-Light", size: 10)!,NSForegroundColorAttributeName:UIColor(red: 43/255, green: 180/255, blue: 0/255, alpha: 1)]
UITabBarItem.appearance().setTitleTextAttributes(attributes, for: .normal)
UITabBarItem.appearance().setTitleTextAttributes(attributes1, for: .selected)
let tabHome = tabbar.items![0]
tabHome.title = "Home" // tabbar titlee
tabHome.image=UIImage(named: "icon_home.png")?.withRenderingMode(.alwaysOriginal) // deselect image
tabHome.selectedImage = UIImage(named: "icon_home.png")?.withRenderingMode(.alwaysOriginal) // select image
tabHome.titlePositionAdjustment.vertical = tabHome.titlePositionAdjustment.vertical-4 // title position change
let tabFoll = tabbar.items![1]
tabFoll.title = "Followed"
tabFoll.image=UIImage(named: "icon_fold.png")?.withRenderingMode(.alwaysOriginal)
tabFoll.selectedImage=UIImage(named: "icon_fold.png")?.withRenderingMode(.alwaysOriginal)
tabFoll.titlePositionAdjustment.vertical = tabFoll.titlePositionAdjustment.vertical-4
let tabMsg = tabbar.items![3]
tabMsg.title = "Message"
tabMsg.image=UIImage(named: "icon_mail.png")?.withRenderingMode(.alwaysOriginal)
tabMsg.selectedImage=UIImage(named: "icon_mail.png")?.withRenderingMode(.alwaysOriginal)
tabMsg.titlePositionAdjustment.vertical = tabMsg.titlePositionAdjustment.vertical-4
return tabbarcntrl
}
Set both images- for select/selected state
You are doing all the things in right way But the only problem is your tabbaritem image is not in correct size .Just look this table for actual size of tabbaritem images.
In swift 4 and 5 you can use the below extension. Remember one thing always pass the same number of images , selected images and title but if you do not want to set title then pass nil in title.
extension UITabBarController{
func setUpImagaOntabbar(_ selectedImage : [UIImage], _ image : [UIImage], _ title : [String]?){
for (index,vals) in image.enumerated(){
if let tab = self.tabBar.items?[index]{
tab.image = image[index]
tab.image = selectedImage[index]
if let tile = title[index]{
tab.title = title[index]
}
}
}
}
}
I'm trying to create a screen where there is going to be a Google map covering the whole screen and a button on the top showing the selected address (where the marker is pointing).
And I want when the user clicks on that button to be presented with a UISearchBar where he can search for locations using the Google Places API.
I have been following the following tutorial:
https://www.youtube.com/watch?v=gRQUoHleCGM
Unfortunately, in my case the search bar is not appearing (although the background is dimmed when I press the button).
Here are some screenshots from before I press the button and after.
And this is the code of my view controller.
class ChooseLocationViewController: UIViewController, GMSMapViewDelegate, UISearchBarDelegate, UISearchControllerDelegate {
let geocoder = GMSGeocoder()
var mapView: GMSMapView = GMSMapView.mapWithFrame(CGRectZero, camera:GMSCameraPosition.cameraWithLatitude(51.515339, longitude: -0.141838, zoom: 16))
var addressButton: UIButton = UIButton()
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
let marker = UIImageView(frame: CGRect(x: 20, y: 20, width: 50, height: 50))
marker.image = UIImage(named: "default-marker")
marker.center.x = self.view.center.x
marker.center.y = self.view.center.y - (self.navigationController?.navigationBar.frame.size.height)!
addressButton = UIButton(frame: CGRect(x: 20, y: 20, width: self.view.frame.size.width - 25, height: 47))
addressButton.center.x = self.view.center.x
addressButton.backgroundColor = UIColor(red: 248/255, green: 248/255, blue: 248/255, alpha: 1.0)
addressButton.layer.borderColor = UIColor(red: 178/255, green: 178/255, blue: 178/255, alpha: 1.0).CGColor
addressButton.layer.borderWidth = 1.0
addressButton.layer.cornerRadius = 5
addressButton.setTitleColor(UIColor(red: 68/255, green: 68/255, blue: 68/255, alpha: 1.0), forState: .Normal)
addressButton.titleLabel?.font = UIFont.systemFontOfSize(13)
addressButton.addTarget(self, action: "showLocationSearch", forControlEvents: .TouchDown)
self.view = mapView
self.view.addSubview(marker)
self.view.addSubview(addressButton)
}
func showLocationSearch() {
let searchController = UISearchController(searchResultsController: nil)
searchController.delegate = self
searchController.searchBar.delegate = self
self.presentViewController(searchController, animated: true, completion: nil)
}
func willPresentSearchController(searchController: UISearchController) {
self.navigationController?.extendedLayoutIncludesOpaqueBars = true
}
func willDismissSearchController(searchController: UISearchController) {
self.navigationController?.extendedLayoutIncludesOpaqueBars = false
}
func mapView(mapView: GMSMapView, idleAtCameraPosition position: GMSCameraPosition) {
let coordinate = position.target
geocoder.reverseGeocodeCoordinate(coordinate) { response, error in
if let address = response?.firstResult() {
if let lines = address.lines {
if (lines.count > 0) {
self.addressButton.setTitle(lines[0], forState: .Normal)
}
}
}
}
}
}
Also, the reason I'm changing the extendedLayoutIncludesOpaqueBars is because I noticed that in other views where I have a search bar, this is necessary for it to be presented properly. In this case, I get exactly the same behavior (search bar is not showing) whether I do that or not.
What am I doing wrong? Did anyone have a similar issue?
Here is what I am trying to do:
Note: The screenshot is taken from an earlier version of iOS
What I have been able to achieve:
Code:
override func viewWillAppear(animated: Bool) {
// Creates image of the Button
let imageCameraButton: UIImage! = UIImage(named: "cameraIcon")
// Creates a Button
let cameraButton = UIButton(type: .Custom)
// Sets width and height to the Button
cameraButton.frame = CGRectMake(0.0, 0.0, imageCameraButton.size.width, imageCameraButton.size.height);
// Sets image to the Button
cameraButton.setBackgroundImage(imageCameraButton, forState: .Normal)
// Sets the center of the Button to the center of the TabBar
cameraButton.center = self.tabBar.center
// Sets an action to the Button
cameraButton.addTarget(self, action: "doSomething", forControlEvents: .TouchUpInside)
// Adds the Button to the view
self.view.addSubview(cameraButton)
}
I did try to create a rounded button in the normal way, but this was the result:
Code Snippet for rounded button:
//Creation of Ronded Button
cameraButton.layer.cornerRadius = cameraButton.frame.size.width/2
cameraButton.clipsToBounds = true
Solution
You need to subclass UITabBarController and then add the button above TabBar's view. A button action should trigger UITabBarController tab change by setting selectedIndex.
Code
The code below only is a simple approach, however for a full supporting iPhone (including X-Series)/iPad version you can check the full repository here: EBRoundedTabBarController
class CustomTabBarController: UITabBarController {
// MARK: - View lifecycle
override func viewDidLoad() {
super.viewDidLoad()
let controller1 = UIViewController()
controller1.tabBarItem = UITabBarItem(tabBarSystemItem: .contacts, tag: 1)
let nav1 = UINavigationController(rootViewController: controller1)
let controller2 = UIViewController()
controller2.tabBarItem = UITabBarItem(tabBarSystemItem: .contacts, tag: 2)
let nav2 = UINavigationController(rootViewController: controller2)
let controller3 = UIViewController()
let nav3 = UINavigationController(rootViewController: controller3)
nav3.title = ""
let controller4 = UIViewController()
controller4.tabBarItem = UITabBarItem(tabBarSystemItem: .contacts, tag: 4)
let nav4 = UINavigationController(rootViewController: controller4)
let controller5 = UIViewController()
controller5.tabBarItem = UITabBarItem(tabBarSystemItem: .contacts, tag: 5)
let nav5 = UINavigationController(rootViewController: controller5)
viewControllers = [nav1, nav2, nav3, nav4, nav5]
setupMiddleButton()
}
// MARK: - Setups
func setupMiddleButton() {
let menuButton = UIButton(frame: CGRect(x: 0, y: 0, width: 64, height: 64))
var menuButtonFrame = menuButton.frame
menuButtonFrame.origin.y = view.bounds.height - menuButtonFrame.height
menuButtonFrame.origin.x = view.bounds.width/2 - menuButtonFrame.size.width/2
menuButton.frame = menuButtonFrame
menuButton.backgroundColor = UIColor.red
menuButton.layer.cornerRadius = menuButtonFrame.height/2
view.addSubview(menuButton)
menuButton.setImage(UIImage(named: "example"), for: .normal)
menuButton.addTarget(self, action: #selector(menuButtonAction(sender:)), for: .touchUpInside)
view.layoutIfNeeded()
}
// MARK: - Actions
#objc private func menuButtonAction(sender: UIButton) {
selectedIndex = 2
}
}
Output
Swift 3 Solution
With a slight adjustment to EricB's solution to have this work for Swift 3, the menuButton.addTarget() method needs to have it's selector syntax changed a bit.
Here is the new menuButton.addTarget() function:
menuButton.addTarget(self, action: #selector(MyTabBarController.menuButtonAction), for: UIControlEvents.touchUpInside)
When defining my TabBarController class, I also add a UITabBarControllerDelegate and placed all of the that in the
override func viewDidAppear(_ animated: Bool) { ... }
For extra clarity, the full code is:
Full Code Solution
import UIKit
class MyTabBarController: UITabBarController, UITabBarControllerDelegate {
// View Did Load
override func viewDidLoad() {
super.viewDidLoad()
}
// Tab Bar Specific Code
override func viewDidAppear(_ animated: Bool) {
let controller1 = UIViewController(self.view.backgroundColor = UIColor.white)
controller1.tabBarItem = UITabBarItem(tabBarSystemItem: UITabBarSystemItem.contacts, tag: 1)
let nav1 = UINavigationController(rootViewController: controller1)
let controller2 = UIViewController()
controller2.tabBarItem = UITabBarItem(tabBarSystemItem: UITabBarSystemItem.contacts, tag: 2)
let nav2 = UINavigationController(rootViewController: controller2)
let controller3 = UIViewController()
let nav3 = UINavigationController(rootViewController: controller3)
nav3.title = ""
let controller4 = UIViewController()
controller4.tabBarItem = UITabBarItem(tabBarSystemItem: UITabBarSystemItem.contacts, tag: 4)
let nav4 = UINavigationController(rootViewController: controller4)
let controller5 = UIViewController()
controller5.tabBarItem = UITabBarItem(tabBarSystemItem: UITabBarSystemItem.contacts, tag: 5)
let nav5 = UINavigationController(rootViewController: controller5)
self.viewControllers = [nav1, nav2, nav3, nav4, nav5]
self.setupMiddleButton()
}
// TabBarButton – Setup Middle Button
func setupMiddleButton() {
let menuButton = UIButton(frame: CGRect(x: 0, y: 0, width: 64, height: 64))
var menuButtonFrame = menuButton.frame
menuButtonFrame.origin.y = self.view.bounds.height - menuButtonFrame.height
menuButtonFrame.origin.x = self.view.bounds.width / 2 - menuButtonFrame.size.width / 2
menuButton.frame = menuButtonFrame
menuButton.backgroundColor = UIColor.red
menuButton.layer.cornerRadius = menuButtonFrame.height/2
self.view.addSubview(menuButton)
menuButton.setImage(UIImage(named: "example"), for: UIControlState.normal)
menuButton.addTarget(self, action: #selector(MyTabBarController.menuButtonAction), for: UIControlEvents.touchUpInside)
self.view.layoutIfNeeded()
}
// Menu Button Touch Action
func menuButtonAction(sender: UIButton) {
self.selectedIndex = 2
// console print to verify the button works
print("Middle Button was just pressed!")
}
}
This is the customTabbarcontroller class which is the subclass of UITabbarcontroller. It's the same idea as given by #EridB. But in his code #Raymond26's issue wasn't solved. So, posting a complete solution written in Swift 3.0
protocol CustomTabBarControllerDelegate
{
func customTabBarControllerDelegate_CenterButtonTapped(tabBarController:CustomTabBarController, button:UIButton, buttonState:Bool);
}
class CustomTabBarController: UITabBarController, UITabBarControllerDelegate
{
var customTabBarControllerDelegate:CustomTabBarControllerDelegate?;
var centerButton:UIButton!;
private var centerButtonTappedOnce:Bool = false;
override func viewDidLayoutSubviews()
{
super.viewDidLayoutSubviews();
self.bringcenterButtonToFront();
}
override func viewDidLoad()
{
super.viewDidLoad()
self.delegate = self;
self.tabBar.barTintColor = UIColor.red;
let dashboardVC = DashboardViewController()
dashboardVC.tabBarItem = UITabBarItem(tabBarSystemItem: .topRated, tag: 1)
let nav1 = UINavigationController(rootViewController: dashboardVC)
let myFriendsVC = MyFriendsViewController()
myFriendsVC.tabBarItem = UITabBarItem(tabBarSystemItem: .featured, tag: 2)
let nav2 = UINavigationController(rootViewController: myFriendsVC)
let controller3 = UIViewController()
let nav3 = UINavigationController(rootViewController: controller3)
nav3.title = ""
let locatorsVC = LocatorsViewController()
locatorsVC.tabBarItem = UITabBarItem(tabBarSystemItem: .downloads, tag: 4)
let nav4 = UINavigationController(rootViewController: locatorsVC)
let getDirectionsVC = GetDirectionsViewController()
getDirectionsVC.tabBarItem = UITabBarItem(tabBarSystemItem: .history, tag: 5)
let nav5 = UINavigationController(rootViewController: getDirectionsVC)
viewControllers = [nav1, nav2, nav3, nav4, nav5]
self.setupMiddleButton()
}
// MARK: - TabbarDelegate Methods
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController)
{
switch viewController
{
case is DashboardViewController:
self.showCenterButton()
case is MyFriendsViewController:
self.showCenterButton()
case is GetDirectionsViewController:
self.showCenterButton()
case is LocatorsViewController:
self.showCenterButton()
default:
self.showCenterButton()
}
}
// MARK: - Internal Methods
#objc private func centerButtonAction(sender: UIButton)
{
// selectedIndex = 2
if(!centerButtonTappedOnce)
{
centerButtonTappedOnce=true;
centerButton.setImage(UIImage(named: "ic_bullseye_white"), for: .normal)
}
else
{
centerButtonTappedOnce=false;
centerButton.setImage(UIImage(named: "ic_bullseye_red"), for: .normal)
}
customTabBarControllerDelegate?.customTabBarControllerDelegate_CenterButtonTapped(tabBarController: self,
button: centerButton,
buttonState: centerButtonTappedOnce);
}
func hideCenterButton()
{
centerButton.isHidden = true;
}
func showCenterButton()
{
centerButton.isHidden = false;
self.bringcenterButtonToFront();
}
// MARK: - Private methods
private func setupMiddleButton()
{
centerButton = UIButton(frame: CGRect(x: 0, y: 0, width: 64, height: 64))
var centerButtonFrame = centerButton.frame
centerButtonFrame.origin.y = view.bounds.height - centerButtonFrame.height
centerButtonFrame.origin.x = view.bounds.width/2 - centerButtonFrame.size.width/2
centerButton.frame = centerButtonFrame
centerButton.backgroundColor = UIColor.red
centerButton.layer.cornerRadius = centerButtonFrame.height/2
view.addSubview(centerButton)
centerButton.setImage(UIImage(named: "ic_bullseye_red"), for: .normal)
centerButton.setImage(UIImage(named: "ic_bullseye_white"), for: .highlighted)
centerButton.addTarget(self, action: #selector(centerButtonAction(sender:)), for: .touchUpInside)
view.layoutIfNeeded()
}
private func bringcenterButtonToFront()
{
print("bringcenterButtonToFront called...")
self.view.bringSubview(toFront: self.centerButton);
}
}
This is the DashboardViewController for complete reference:
class DashboardViewController: BaseViewController, CustomTabBarControllerDelegate
{
override func viewDidLoad()
{
super.viewDidLoad()
(self.tabBarController as! CustomTabBarController).customTabBarControllerDelegate = self;
}
override func viewWillAppear(_ animated: Bool)
{
super.viewWillAppear(animated);
(self.tabBarController as! CustomTabBarController).showCenterButton();
}
override func viewWillDisappear(_ animated: Bool)
{
super.viewWillDisappear(animated);
self.hidesBottomBarWhenPushed = false;
(self.tabBarController as! CustomTabBarController).hideCenterButton();
}
override func viewWillLayoutSubviews()
{
super.viewWillLayoutSubviews();
if(!isUISetUpDone)
{
self.view.backgroundColor = UIColor.lightGray
self.title = "DASHBOARD"
self.prepareAndAddViews();
self.isUISetUpDone = true;
}
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
}
//MARK: CustomTabBarControllerDelegate Methods
func customTabBarControllerDelegate_CenterButtonTapped(tabBarController: CustomTabBarController, button: UIButton, buttonState: Bool)
{
print("isDrive ON : \(buttonState)");
}
//MARK: Internal Methods
func menuButtonTapped()
{
let myFriendsVC = MyFriendsViewController()
myFriendsVC.hidesBottomBarWhenPushed = true;
self.navigationController!.pushViewController(myFriendsVC, animated: true);
}
//MARK: Private Methods
private func prepareAndAddViews()
{
let menuButton = UIButton(frame: CGRect(x: 100, y: 100, width: 100, height: 50))
menuButton.titleLabel?.text = "Push"
menuButton.titleLabel?.textColor = UIColor.white
menuButton.backgroundColor = UIColor.red;
menuButton.addTarget(self, action: #selector(DashboardViewController.menuButtonTapped), for: .touchUpInside)
self.view.addSubview(menuButton);
}
}
with StoryBoard:
Click the tab bar button within the view controller of the particular tab bar item you want to make prominent,
Remove the text, just set the image inset top to -25 of the tab bar button.
Check Like Below image