Messagekit Navigation bar is not showing up - ios

How can i show the default or custom navigation bar ? tried everything but nothing works , It seems like nothing is on the top , its a messageViewcontroller of messagekit and couldn't find any delegate method for navigation bar , it would be nice if someone educate me about this ..
My Code
override func viewDidLoad() {
messagesCollectionView = MessagesCollectionView(frame: .zero, collectionViewLayout: CustomMessagesFlowLayout())
messagesCollectionView.register(CustomCell.self)
super.viewDidLoad()
messagesCollectionView.messagesDataSource = self
messagesCollectionView.messagesLayoutDelegate = self
messagesCollectionView.messagesDisplayDelegate = self
messagesCollectionView.messageCellDelegate = self
messageInputBar.delegate = self
configureMessageInputBar()
configureInputBarItems()
updateTitleView(title: "Hanzala", subtitle: "Online")
}
import UIKit
extension UIViewController {
func updateTitleView(title: String, subtitle: String?, baseColor: UIColor = .white) {
let titleLabel = UILabel(frame: CGRect(x: 0, y: -2, width: 0, height: 0))
titleLabel.backgroundColor = UIColor.clear
titleLabel.textColor = baseColor
titleLabel.font = UIFont.systemFont(ofSize: 15)
titleLabel.text = title
titleLabel.textAlignment = .center
titleLabel.adjustsFontSizeToFitWidth = true
titleLabel.sizeToFit()
let subtitleLabel = UILabel(frame: CGRect(x: 0, y: 18, width: 0, height: 0))
subtitleLabel.textColor = baseColor.withAlphaComponent(0.95)
subtitleLabel.font = UIFont.systemFont(ofSize: 12)
subtitleLabel.text = subtitle
subtitleLabel.textAlignment = .center
subtitleLabel.adjustsFontSizeToFitWidth = true
subtitleLabel.sizeToFit()
let titleView = UIView(frame: CGRect(x: 0, y: 0, width: max(titleLabel.frame.size.width, subtitleLabel.frame.size.width), height: 30))
titleView.addSubview(titleLabel)
if subtitle != nil {
titleView.addSubview(subtitleLabel)
} else {
titleLabel.frame = titleView.frame
}
let widthDiff = subtitleLabel.frame.size.width - titleLabel.frame.size.width
if widthDiff < 0 {
let newX = widthDiff / 2
subtitleLabel.frame.origin.x = abs(newX)
} else {
let newX = widthDiff / 2
titleLabel.frame.origin.x = newX
}
navigationItem.titleView = titleView
}
}
I want the navigation bar like this
Pushing ChatViewController in NavigationController
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let model = Api.Params.chatUser[indexPath.row]
openConversation(model)
}
func openConversation(_ model: ChatUser) {
Api.Params.inputRecieverId = model.userId
let id = String(requestManager.instance.userID)
let vc = ChatViewController(recieverId: model.userId, senderId: id, conversationId: "Eman-Conversation-\(id)-\(model.userId)")
vc.title = model.username
vc.navigationItem.largeTitleDisplayMode = .never
navigationController?.pushViewController(vc, animated: true)
}

You've to embed the MessageViewcontroller inside a UINavigationController and use it.
let navigationController = UINavigationController(rootViewController: MessageViewcontroller())
If the controller that you're pushing MessageViewcontroller onto already has a navigationController then push the MessageViewcontroller into the navigational stack instead of presenting.
let messageViewcontroller = MessageViewcontroller()
navigationController?.pushViewController(messageViewcontroller, animated: true)

Related

How to add and open a nib as child viewcontroller progrmatically from UITabBarController

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)
}
}

There is change add to atop duplicate header, but there is a stretch effect?

enter image description hereThere is a stretch effect.But the additional header is duplicated , only without data.Can anyone correct my code that I wrote extra or incorrectly called the header?.I have custom Header xib. link tutorial https://mobikul.com/table-view-stretch-header-parallax-animation-in-swift/
My code:
var headerView: CustomSoccerHeaderView? = {
return Bundle.main.loadNibNamed("CustomSoccerHeaderView", owner: nil, options: nil)!.first as! CustomSoccerHeaderView
}()
override func viewDidLoad() {
super.viewDidLoad()
let backButton = UIBarButtonItem()
backButton.title = ""
self.navigationController?.navigationBar.topItem?.backBarButtonItem = backButton
// self.navigationItem.rightBarButtonItem = barButton
// self.navigationItem.rightBarButtonItem?.tintColor = UIColor.universalColorYellow
let yourBackImage = UIImage(named: "backItem")
self.navigationController?.navigationBar.backIndicatorImage = yourBackImage
self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = yourBackImage
self.navigationController?.navigationItem.leftItemsSupplementBackButton = true
self.navigationController?.navigationBar.tintColor = UIColor.universalColorYellow
//title = detailSoccer.detailTitleS
let nib: UINib = UINib(nibName: "CustomSoccerHeaderView", bundle: nil)
tableView.register(nib, forHeaderFooterViewReuseIdentifier: "CustomSoccerHeaderView")
tableView.tableFooterView = UIView(frame: .zero)
tableView.estimatedRowHeight = 280
headerView?.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 350)
tableView.tableHeaderView = headerView
tableView.tableHeaderView = nil
tableView.contentInset = UIEdgeInsets(top: 350, left: 0, bottom: 0, right: 0)
tableView.addSubview(headerView!)
tableView.separatorStyle = .none
tableView.delegate = self
tableView.dataSource = self
tableView.register(UINib(nibName:"FootTableViewCell",bundle:nil), forCellReuseIdentifier: "cellSoc")
self.view.addSubview(tableView)
tableView.rowHeight = UITableView.automaticDimension
tableView.reloadData()
loadMatchSoccer()
tableView.rowHeight = UITableView.automaticDimension
}
That's going to stretch the effect:
func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
self.tableView.reloadData()
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if headerView != nil {
let yPos: CGFloat = -scrollView.contentOffset.y
if yPos > 0 {
var imgRect: CGRect? = headerView?.frame
imgRect?.origin.y = scrollView.contentOffset.y
imgRect?.size.height = 350 + yPos - 350
headerView?.frame = imgRect!
self.tableView.sectionHeaderHeight = (imgRect?.size.height)!
}
}
}
This is the code for the header section of my file xib class.I think I make a mistake in inheriting the header or loading addsubview.Maybe someone more experienced can tweak my code.I would appreciate that.
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: "CustomSoccerHeaderView") as! CustomSoccerHeaderView
header.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 350)
header.clickBravisso = detailSoccer
header.nameHeader.text = detailSoccer.matchS
header.countBravo.text = ""
// header.bravoBtn.addTarget(CustomSoccerHeaderView(), action: #selector(CustomSoccerHeaderView.likeBtn(_:)), for: UIControlEvents.touchUpInside)
detailSoccer.imagePrS.getDataInBackground { (data, error) in
header.imageHeader.image = error == nil ? UIImage(data: data!) : nil
}
return header
}

Create a Utility function for UIActivityIndicator to show and hide depending on the condition in controller

Hello I have created a swift file in which I wrote some utility functions which I used in multiple controllers. I also wrote function for UIActivityIndicator. But somehow its not working as expected.
Here is my function
static func showIndicatorView(backgroundView: UIView,controller: UIViewController)->UIActivityIndicatorView{
let loadingIndicator = UIActivityIndicatorView(frame: CGRectMake(0, 0, 50, 50))
let backgroundView = UIView()
backgroundView.layer.cornerRadius = 05
backgroundView.clipsToBounds = true
backgroundView.opaque = false
backgroundView.backgroundColor = UIColor(white: 0.0, alpha: 0.6)
loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.Gray
loadingIndicator.color = UIColor.whiteColor()
loadingIndicator.startAnimating()
let loadingLabel = UILabel()
loadingLabel.text = "Loading..."
loadingLabel.textColor = UIColor.whiteColor()
let textSize: CGSize = loadingLabel.text!.sizeWithAttributes([NSFontAttributeName: loadingLabel.font ])
loadingLabel.frame = CGRectMake(50, 0, textSize.width, textSize.height)
loadingLabel.center.y = loadingIndicator.center.y
backgroundView.frame = CGRectMake(0, 0, textSize.width + 70, 50)
backgroundView.center = controller.view.center;
controller.view.addSubview(backgroundView)
backgroundView.addSubview(loadingIndicator)
backgroundView.addSubview(loadingLabel)
return loadingIndicator
}
I am doing this in controllers in order to show and hide the indicator
show
Utility.showIndicatorView(backgroundView, controller: self).startAnimating()
hide
Utility.showIndicatorView(backgroundView, controller: self).startAnimating()
Sometimes UiIndicatorView background doesn't remove from the controller. Please check my code and let me know how can I show and hide the uiindicator in one or two lines
Create a class for your loading view and add functions to show and hide the view like this:
import UIKit
class LoadingView: UIView {
override init (frame : CGRect) {
super.init(frame : frame)
let loadingIndicator = UIActivityIndicatorView(frame: CGRectMake(0, 0, 50, 50))
let backgroundView = UIView()
backgroundView.layer.cornerRadius = 05
backgroundView.clipsToBounds = true
backgroundView.opaque = false
backgroundView.backgroundColor = UIColor(white: 0.0, alpha: 0.6)
loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.Gray
loadingIndicator.color = UIColor.whiteColor()
loadingIndicator.startAnimating()
let loadingLabel = UILabel()
loadingLabel.text = "Loading..."
loadingLabel.textColor = UIColor.whiteColor()
let textSize: CGSize = loadingLabel.text!.sizeWithAttributes([NSFontAttributeName: loadingLabel.font ])
loadingLabel.frame = CGRectMake(50, 0, textSize.width, textSize.height)
loadingLabel.center.y = loadingIndicator.center.y
backgroundView.frame = CGRectMake(0, 0, textSize.width + 70, 50)
backgroundView.center = self.center;
self.addSubview(backgroundView)
backgroundView.addSubview(loadingIndicator)
backgroundView.addSubview(loadingLabel)
}
convenience init () {
self.init(frame:UIScreen.mainScreen().bounds)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func showLoadingView() {
if let rootViewController = UIApplication.topViewController() {
rootViewController.view.addSubview(self)
self.bringSubviewToFront(rootViewController.view)
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
}
}
func hideLoadingView() {
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
self.removeFromSuperview()
}
}
// Get the visible ViewController
extension UIApplication {
class func topViewController(base: UIViewController? = UIApplication.sharedApplication().keyWindow?.rootViewController) -> UIViewController? {
if let nav = base as? UINavigationController {
return topViewController(nav.visibleViewController)
}
if let tab = base as? UITabBarController {
let moreNavigationController = tab.moreNavigationController
if let top = moreNavigationController.topViewController where top.view.window != nil {
return topViewController(top)
} else if let selected = tab.selectedViewController {
return topViewController(selected)
}
}
if let presented = base?.presentedViewController {
return topViewController(presented)
}
return base
}
}
Then init your loading view in your ViewController.
let lv = LoadingView()
lv.showLoadingView()
lv.hideLoadingView()

Make custom button on Tab Bar rounded

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

UINavigationItem TitleView disappears

I am trying to create a custom titleView for a navigation bar. I am able to set the titleView in the root view controller that is embedded in a navigation controller.
When I push the second view controller onto the stack and try to set the titleView for this view controller it does not work. The titleView quickly appears and disappears. When I go back to the previous view controller this titleView quickly appears and disappears now also.
Does anyone know why this is happening or how to set the titleView correctly without flashing and disappearing?
class FirstViewController: UIViewController {
var titleView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
addTitleView()
}
func addTitleView() {
titleView = UIView(frame: CGRect(x: 0, y: 0, width: 150, height: 44))
let companyLabel = UILabel(frame: CGRect(x: 0, y: 3, width: 150, height: 11))
companyLabel.text = "CPS Dashboard"
companyLabel.textColor = UIColor.grayColor()
companyLabel.textAlignment = .Center
companyLabel.font = UIFont.systemFontOfSize(9)
titleView.addSubview(companyLabel)
let titleLabel = UILabel(frame: CGRect(x: 0, y: 16, width: 150, height: 18))
titleLabel.text = "Dashboard"
titleLabel.textColor = UIColor.blackColor()
titleLabel.textAlignment = .Center
titleLabel.font = UIFont.systemFontOfSize(15)
titleView.addSubview(titleLabel)
navigationItem.titleView = titleView
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "Show" {
let controller = segue.destinationViewController as! SecondViewController
controller.titleView = titleView
}
}
}
The second viewcontroller:
class SecondViewController: UIViewController {
var titleView: UIView?
override func viewDidLoad() {
super.viewDidLoad()
if let titleView = titleView {
navigationItem.titleView = titleView
}
}
}
I found a solution. I copied addTitleView() method from FirstViewController into SecondViewController, and called both of them in viewDidLoad(). This worked exactly as I wanted it to. For some reason it was not working to pass the titleView forward as a property and assigning it to navigationItem.titleView.
class FirstViewController: UIViewController {
var titleView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
addTitleView()
}
func addTitleView() {
titleView = UIView(frame: CGRect(x: 0, y: 0, width: 150, height: 44))
let companyLabel = UILabel(frame: CGRect(x: 0, y: 3, width: 150, height: 11))
companyLabel.text = "CPS Dashboard"
companyLabel.textColor = UIColor.grayColor()
companyLabel.textAlignment = .Center
companyLabel.font = UIFont.systemFontOfSize(9)
titleView.addSubview(companyLabel)
let titleLabel = UILabel(frame: CGRect(x: 0, y: 16, width: 150, height: 18))
titleLabel.text = "Dashboard"
titleLabel.textColor = UIColor.blackColor()
titleLabel.textAlignment = .Center
titleLabel.font = UIFont.systemFontOfSize(15)
titleView.addSubview(titleLabel)
navigationItem.titleView = titleView
}
}
The second viewcontroller:
class SecondViewController: UIViewController {
var titleView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
addTitleView()
}
func addTitleView() {
titleView = UIView(frame: CGRect(x: 0, y: 0, width: 150, height: 44))
let companyLabel = UILabel(frame: CGRect(x: 0, y: 3, width: 150, height: 11))
companyLabel.text = "CPS Dashboard"
companyLabel.textColor = UIColor.grayColor()
companyLabel.textAlignment = .Center
companyLabel.font = UIFont.systemFontOfSize(9)
titleView.addSubview(companyLabel)
let titleLabel = UILabel(frame: CGRect(x: 0, y: 16, width: 150, height: 18))
titleLabel.text = "Dashboard"
titleLabel.textColor = UIColor.blackColor()
titleLabel.textAlignment = .Center
titleLabel.font = UIFont.systemFontOfSize(15)
titleView.addSubview(titleLabel)
navigationItem.titleView = titleView
}
}
My solution is simple, and it works:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let tv = navigationItem.titleView {
print("transform", tv.transform)) // is always identity
let bounds = tv.bounds
print("bounds", bounds) // its origin may not be zero.
tv.bounds = CGRect(origin: .zero, size: bounds.size)
print("new bounds", tv.bounds)
}
}
Using Xcode's view debugger, you will find that titleView.bounds.origin is not zero.
How to let it happen again, two steps:
1. UIViewController A and B; A has custom navigationItem.titleView, B hides navigationBar in its viewWillAppear(); when B poped, A.viewWillAppear() setNavigationBar(hidden: false, animated: true)
2. user-driven popViewController is canceled by lifting your hand.
Then you will found, A's navigationBar is blank.
I was having this same issue, but none of the above solutions fixed it for me. My issue was that I was setting translatesAutoresizingMaskIntoConstraints to false. I imagine this caused the appearing/disappearing because it needs to be set to true in order to constrain the view internally to the navigation bar.

Resources