I'm getting to grips with Swift 4 and Xcode.
I can't figure out how to close a WKWebView after it has been opened!
I am using it to display a PDF document, and have added a Navigation Bar with a 'Done' button.
I have figured out how to got to close it and go to the Root UIViewController, however I want it to go to a View Controller called 'DocumentsViewController'.
Below is the code I am working with, however I believe the line I am trying to fix is:
let doneItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.done, target: nil, action: #selector(selectAction(_:)))
With selectAction being:
#objc func selectAction(_ sender:UIBarButtonItem) -> Void {
//print("Select Clicked")
self.view.window?.rootViewController?.dismiss(animated: true, completion: nil)
}
I've spent hours trying to figure this out! How can I make it so when I click the done button it closes the WKWebView and goes to the 'DocumentsViewController'?
#objc func selectAction(_ sender:UIBarButtonItem) -> Void {
//print("Select Clicked")
self.view.window?.rootViewController?.dismiss(animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
if let url = Bundle.main.url(forResource: pdfTitle, withExtension: "pdf") {
let webView = WKWebView(frame: self.view.frame)
let urlRequest = URLRequest(url: url)
webView.load(urlRequest as URLRequest)
self.view.addSubview(webView)
self.tabBarController?.tabBar.isHidden = true
let screenSize: CGRect = UIScreen.main.bounds
let navBar: UINavigationBar = UINavigationBar(frame: CGRect(x: 0, y: 0, width: screenSize.width, height: 44))
self.view.addSubview(navBar);
let navItem = UINavigationItem(title: "");
let doneItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.done, target: nil, action: #selector(selectAction(_:)))
navItem.rightBarButtonItem = doneItem;
navBar.setItems([navItem], animated: false);
// Get height of status bar (iPhone X introduced a new status bar)
let statusBarHeight = UIApplication.shared.statusBarFrame.height
// Initialize the frame
webView.frame = CGRect.init(x: 0, y: statusBarHeight, width: view.bounds.maxX, height: view.bounds.maxY)
// Set background color of status bar (optional)
self.view.backgroundColor = UIColor(red: 248/255.0, green: 248/255.0, blue: 248/255.0, alpha: 1.0)
}
Just add your new view to the navigation stack...
#objc func selectAction(_ sender:UIBarButtonItem) -> Void {
let newViewController = DocumentsViewController()
self.navigationController?.pushViewController(newViewController, animated: true)
}
Related
I'm super new to iOS app development using Swift and Xcode. Right now, I'm trying to create a base view with a navbar for all my views instead of using a nav controller. When I started in landscape mode, the navbar looks fine, but the height looks off when I switch to portrait mode. When I start in portrait mode, landscape mode looks off where the nav bar is only half of the full length. It seems that when I change to landscape mode, no nav bar is being drawn and it used the old one... In the code below, I have an orientation listener which draws the navbar again, but it doesn't seem to work.
import UIKit
class BaseViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(BaseViewController.rotated), name: UIDevice.orientationDidChangeNotification, object: nil)
}
deinit {
NotificationCenter.default.removeObserver(self, name: UIDevice.orientationDidChangeNotification, object: nil)
}
#objc func rotated() {
if UIDevice.current.orientation.isLandscape {
print("Landscape")
createNavBarLandscape()
} else {
print("Portrait")
createNavBarPortrait()
}
}
func createNavBarLandscape() {
let navBar = UINavigationBar(frame: CGRect(x: 0, y: 50, width: view.frame.size.width * 2, height: 24))
view.addSubview(navBar)
navBar.barTintColor = .white
let navItem = UINavigationItem(title: "logo")
let logo = UIImage(named: "logo.png")
let imageView = UIImageView(image:logo)
navItem.titleView = imageView
navBar.setItems([navItem], animated: false)
}
func createNavBarPortrait() {
let navBar = UINavigationBar(frame: CGRect(x: 0, y: 50, width: view.frame.size.width, height: 44))
view.addSubview(navBar)
navBar.barTintColor = .white
let navItem = UINavigationItem(title: "logo")
let logo = UIImage(named: "logo.png")
let imageView = UIImageView(image:logo)
navItem.titleView = imageView
navBar.setItems([navItem], animated: false)
}
}
Starting in portrait mode:
Portrait mode:
Landscape mode:
Starting in landscape mode:
Landscape mode:
Portrait mode:
Give this a try...
class MyBaseViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let navBar = UINavigationBar()
view.addSubview(navBar)
navBar.barTintColor = .white
let navItem = UINavigationItem(title: "logo")
let imageView = UIImageView()
if let logo = UIImage(named: "logo") {
imageView.image = logo
}
navItem.titleView = imageView
navBar.setItems([navItem], animated: false)
navBar.translatesAutoresizingMaskIntoConstraints = false
// respect safe area
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
navBar.topAnchor.constraint(equalTo: g.topAnchor),
navBar.leadingAnchor.constraint(equalTo: g.leadingAnchor),
navBar.trailingAnchor.constraint(equalTo: g.trailingAnchor),
])
}
}
I have a UITabBarController and four UIViewControllers associated with it. I created a custom view in the place of the navigation bar in the UITabBarController subclass, so this custom view will be common for all the UIViewControllers. There are two buttons in the custom view when one of the buttons is tapped, I want to add and open the "FilesViewController.xib" as a child view controller to the currently active UIViewController.
Below is what I tried so far and it is not adding the FilesViewController.xib as a child view controller. What I'm doing wrong?
import UIKit
class RootTabBarController: UITabBarController {
var topBarHeight:CGFloat = 87.0
override func viewDidLoad() {
super.viewDidLoad()
let containerView = UIView()
self.view.addSubview(containerView)
containerView.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: topBarHeight)
containerView.backgroundColor = UIColor.init(red: 113.0/255.0, green: 193.0/255.0, blue: 34.0/255.0, alpha: 1.0)
let filesButton = UIButton()
containerView.addSubview(filesButton)
filesButton.frame = CGRect(x: logoutButton.frame.origin.x-46, y: 40, width: 40, height: 40)
filesButton.setImage(UIImage(named: "folder"), for: .normal)
filesButton.addTarget(self, action: #selector(openFileViewController(_:)), for: .touchUpInside)
}
func configureFilesController() // Old Function
{
let filesController = FilesViewController()
self.addChild(filesController)
self.view.addSubview(filesController.view)
filesController.didMove(toParent: selectedViewController)
let height = view.frame.height
let width = view.frame.width
filesController.view.frame = CGRect(x: 0, y: self.view.frame.maxY, width: width, height: height)
}
func configureFilesController() // New One
{
filesController = FilesViewController.init(nibName: "FilesViewController", bundle: nil)
self.addChild(filesController)
self.view.addSubview(filesController.view)
let height = view.bounds.height
let width = view.bounds.width
filesController.view.frame = CGRect(x: 0, y: height/2, width: width, height: height/2)
filesController.view.layer.cornerRadius = 5.0
filesController.didMove(toParent: self)
}
#objc func openFileViewController(_ sender: UIButton) {
print("Tapped")
configureFilesController()
}
}
import UIKit
class FilesViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .clear
}
override func viewWillAppear(_ animated: Bool) {
prepareBackGroundView()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// Adding the below line worked like what I was expecting
self.view.frame = CGRect(x: 0, y: self.view.bounds.height, width: self.view.bounds.width, height: self.view.frame.height)
UIView.animate(withDuration: 0.3) { [weak self] in
let frame = self?.view.frame
let yComponent = UIScreen.main.bounds.height - 200
self?.view.frame = CGRect(x: 0, y: yComponent, width: frame!.width, height: frame!.height)
}
}
func prepareBackGroundView(){
let blurEffect = UIBlurEffect.init(style: .dark)
let visualEffect = UIVisualEffectView.init(effect:blurEffect)
let blurView = UIVisualEffectView.init(effect: blurEffect)
blurView.contentView.addSubview(visualEffect)
visualEffect.frame = UIScreen.main.bounds
blurView.frame = UIScreen.main.bounds
view.insertSubview(blurView, at: 0)
}
}
you can find the solution here stackoverflow answer. by using this answer I have created sample program. Here I added two tabs one child controller created in story board and another one created in xib.
my RootTabBarController looks like
import UIKit
class RootTabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let child1 = storyBoard.instantiateViewController(identifier: "Child1ViewController")
let child2 = Child2ViewCOntroller.init(nibName: "Child2ViewCOntroller", bundle: nil)
let tabItem1:UITabBarItem = UITabBarItem(tabBarSystemItem: .contacts, tag: 0) // customise TabBar with images and title
let tabItem2:UITabBarItem = UITabBarItem(tabBarSystemItem: .bookmarks, tag: 1)
child1.tabBarItem = tabItem1
child2.tabBarItem = tabItem2
self.setViewControllers([child1,child2], animated: true)
}
}
class MainVC: UIViewController {
var datasourceForUsers :UserPicker!
var userPicker :UIPickerView!
var toolBar: UIToolbar!
override func viewDidLoad() {
super.viewDidLoad()
userPicker = UIPickerView()
toolBar = UIToolbar()
datasourceForUsers = UserPicker()
}
#IBAction func onMoreTapped(){
NotificationCenter.default.post(name: NSNotification.Name("ToggleSideMenu"), object: nil)
}
#IBAction func showRegisteredUsers(_ sender: Any) {
createUserPicker()
configureToolBar(toolBar)
}
func createUserPicker() {
userPicker.dataSource = datasourceForUsers
userPicker.delegate = datasourceForUsers
//Customizations
userPicker.backgroundColor = .black
userPicker.frame = CGRect.init(x: 0.0, y: UIScreen.main.bounds.size.height - 300, width: UIScreen.main.bounds.size.width, height: 300)
self.view.addSubview(userPicker)
}
func configureToolBar(_ toolBar:UIToolbar ){
toolBar.sizeToFit()
toolBar.barTintColor = .black
toolBar.tintColor = .white
let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(MainVC.dismissKeyboard))
toolBar.setItems([doneButton], animated: false)
toolBar.isUserInteractionEnabled = true
toolBar.frame = CGRect.init(x: 0.0, y: UIScreen.main.bounds.size.height - 300, width: UIScreen.main.bounds.size.width, height: 50)
self.view.addSubview(toolBar)
}
override func viewWillAppear(_ animated: Bool) {
userPicker.reloadAllComponents()
toolBar.reloadInputViews()
}
#objc func cancelDatePicker(){
self.view.endEditing(true)
}
#objc func dismissKeyboard() {
self.resignFirstResponder()
}
}
I used above code to show some data on UIPickerView .It works fine.But When I change the datasource(Add new Data) where the data is stored it does not reflect on the UI picker.In order to do that I have to run the application again.Second thing is I couldn't close the UI picker with transition.
I have the scheme: UITabBarViewController (with 3 tabs).
In all that tabs I don't want to show navigation menu on top.
And from the first tab, I want to push another view controller from button click that will have "back" button (and top toolbar with "cancel")
I tried some ways - in storyboard with push segue - no back button.
Probably because i don't have navigation view controller, so my navigation stack is empty.
Programmatically:
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewController(withIdentifier: "AddCoinTableViewController") as! AddCoinTableViewController
self.present(nextViewController, animated:true, completion:nil)
If I embed tabs in navigation controller, then I have top toolbar (which I don't want).
Any ideas how to make it?
You can't achieve navigation functionality without using UINavigationController. I mean you have to do all animation kind of stuff on your own, and I think that's not a good idea. Rather than that, you can use UINavigationController, and if you don't want to show navigationBar at some viewController, than do as follows for those view controllers.
override func viewWillApear() {
super.viewDidLoad()
self.navigationController?.isNavigationBarHidden = true
}
override func viewWillDisappear(animated: Bool) {
self.navigationController?.isNavigationBarHidden = false
}
You can embed the navigation controller at your first tab controller (or any you want), and hide it at the controllers you don't want on their viewDidLoad like this:
self.navigationController?.isNavigationBarHidden = true
Doing this, you will be able to see the back Button at the controllers you pushed and didn't hide the navigationBar.
Make sure you push the controller using the navigation controller like this:
self.navigationController?.pushViewController(YOUR VIEW CONTROLLER, animated: true)
The below code will allow you to create your own Navigation handling class and have the "push" "pop" animation that UINavigationController has.. You can create a new project, copy paste the below into ViewController.swift and see for yourself..
Now you can give any UIViewController navigation controller abilities..
import UIKit
class NavigationHandler : NSObject, UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning, UINavigationBarDelegate {
private var isPresenting: Bool = false
private weak var controller: UIViewController?
init(controller: UIViewController) {
super.init()
self.controller = controller
controller.transitioningDelegate = self
let navigationBar = UINavigationBar()
controller.view.addSubview(navigationBar)
NSLayoutConstraint.activate([
navigationBar.leftAnchor.constraint(equalTo: controller.view.leftAnchor),
navigationBar.rightAnchor.constraint(equalTo: controller.view.rightAnchor),
navigationBar.topAnchor.constraint(equalTo: controller.view.safeAreaLayoutGuide.topAnchor)
])
navigationBar.translatesAutoresizingMaskIntoConstraints = false
navigationBar.delegate = self
let item = UINavigationItem(title: controller.title ?? "")
let barButton = UIBarButtonItem(title: "Back", style: .done, target: self, action: #selector(onBackButton(button:)))
item.leftBarButtonItems = [barButton]
navigationBar.setItems([item], animated: true)
}
func position(for bar: UIBarPositioning) -> UIBarPosition {
return .topAttached
}
#objc
private func onBackButton(button: UIBarButtonItem) {
self.controller?.dismiss(animated: true, completion: nil)
}
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
self.isPresenting = true;
return self;
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
self.isPresenting = false;
return self;
}
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.25;
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let duration = self.transitionDuration(using: transitionContext)
let fromController = transitionContext.viewController(forKey: .from)
let toController = transitionContext.viewController(forKey: .to)
let containerView = transitionContext.containerView
if self.isPresenting {
let frame = fromController!.view.frame
containerView.addSubview(toController!.view)
toController?.view.frame = CGRect(x: frame.origin.x + frame.width, y: frame.origin.y, width: frame.width, height: frame.height)
UIView.animate(withDuration: duration, animations: {
fromController?.view.frame = CGRect(x: frame.origin.x - frame.size.width, y: frame.origin.y, width: frame.size.width, height: frame.size.height)
toController?.view.frame = frame
}, completion: { (completed) in
transitionContext.completeTransition(true)
})
}
else {
let frame = fromController!.view.frame
containerView.insertSubview(toController!.view, at: 0)
toController?.view.frame = CGRect(x: frame.origin.x - frame.size.width, y: frame.origin.y, width: frame.size.width, height: frame.size.height)
UIView.animate(withDuration: duration, animations: {
fromController?.view.frame = CGRect(x: frame.origin.x + frame.width, y: frame.origin.y, width: frame.width, height: frame.height)
toController?.view.frame = frame
}, completion: { (completed) in
transitionContext.completeTransition(true)
})
}
}
}
View Controllers for testing:
class ViewController : UIViewController {
private var navigationHandler: NavigationHandler?
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(type: .custom)
button.setTitle("Push Controller", for: .normal)
button.setTitleColor(UIColor.red, for: .normal)
button.layer.borderColor = UIColor.black.cgColor
button.layer.borderWidth = 1.0
button.layer.cornerRadius = 5.0
button.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(button)
NSLayoutConstraint.activate([
button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
button.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
button.heightAnchor.constraint(equalToConstant: 45.0),
button.widthAnchor.constraint(equalToConstant: 150.0)
])
button.addTarget(self, action: #selector(onPush(button:)), for: .touchUpInside)
}
#objc
private func onPush(button: UIButton) {
let child = ChildViewController()
self.navigationHandler = NavigationHandler(controller: child)
self.present(child, animated: true, completion: nil)
}
}
class ChildViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.blue
}
}
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