I have two viewControllers.
vc1 -> presentVC -> vc2
vc2 inherit UINavigationController
I want to set title & backButton in vc2,but it doesn't work.
class vc2: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
// set title!!!
//self.navigationItem.title = "123"
//self.navigationController?.navigationBar.topItem?.title = "123"
//self.title = "123"
//self.navigationBar.topItem?.title = "123"
//self.navigationItem.title = "123"
// set backButton!!!
let navButtonWidth:CGFloat = 44
let backButton:UIButton = UIButton()
backButton.setImage(backImage, for: .normal)
backButton.addTarget(self, action: #selector(back), for: .touchUpInside)
self.navigationItem.leftBarButtonItems = [UIBarButtonItem(customView: backButton)]
}
Place the code below in perform(segue) or viewWillDissappear depended on how do you do your presentation - via Storyboard segue or manually from code.
let backButton = UIBarButtonItem()
backButton.title = "whatever_you_want"
navigationItem.backBarButtonItem = backButton
And in viewDidLoad of your vc2 simply put
navigationItem.title = "Controller title"
I can change it in storyboard Or change it in code.
I usually do this.
First hide navigation bar from default navigation controller.
navigationController?.navigationBar.hidden = true
Create navigation bar in storyboard and outlet it.
#IBOutlet weak var navigationBar: UINavigationBar!
Create custom navigation item.
private lazy var customNavigationItem: UINavigationItem = {
let navigationItem = UINavigationItem()
let backButton = UIBarButtonItem(image: UIImage(named: "cancel_icon"), style: .Plain, target: self, action: #selector(cancelTapped))
navigationItem.leftBarButtonItem = backButton
navigationItem.title = "Your Title"
return navigationItem
}()
Add custom navigation item to navigation bar
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
navigationController?.navigationBar.hidden = true
navigationBar.setItems([customNavigationItem], animated: false)
}
Hope it help.
Related
I want customised navigation bar back button title with action.
My Image :
I need back button like this. Here i added text successfully, but not back arrow. Here my code has action for back button.
This is my code
//Custom barButtonItem with custom alert function
self.navigationItem.hidesBackButton = true
let newBackButton = UIBarButtonItem(title: "< Dialer", style: .plain, target: self, action: #selector(back(sender:)))
self.navigationItem.leftBarButtonItem = newBackButton
When i add above code it's getting like this.
func backButtonConfiguration(_ title : String, backImageName : String) {
let backImage : UIImage = UIImage(named: backImageName)!
self.navigationBar.backIndicatorImage = backImage.withRenderingMode(.alwaysTemplate)
self.navigationBar.backIndicatorTransitionMaskImage = backImage
self.navigationBar.backItem?.title = title
}
Update
if we need custom action for back button then we have to add custom BarButtonItem. And if we need bar back button look same as built in back button then we can create custom view and use it it as a bar button item
weak var customView : UIView!
lazy var leftBarButtonView : UIBarButtonItem! = {
let btnBack = UIBarButtonItem(customView: customView)
let gesture = UITapGestureRecognizer(target: self, action: #selector(btnButtonClicked(_:)))
gesture.numberOfTapsRequired = 1
self.customView.addGestureRecognizer(gesture)
self.customView.isUserInteractionEnabled = true
return btnBack
}()
#objc func btnButtonClicked(_ gesture : UITapGestureRecognizer) {
self.navigationController?.popViewController(animated: true)
}
self.navigationItem.leftBarButtonItems = [leftBarButtonView]
I've watched a lot of questions like this and didn't find an answer for my question.
That how i do now:
APPDELEGATE (didFinishLaunchingWithOptions)
// Text
let barButtonItem = UIBarButtonItem.appearance()
barButtonItem.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.clear], for: UIControlState.normal)
barButtonItem.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.clear], for: UIControlState.highlighted)
// Image
let backImage = UIImage(named: "arrow_left"
UINavigationBar.appearance().backIndicatorImage = backImage
UINavigationBar.appearance().backIndicatorTransitionMaskImage = backImage
And this almost fit to what i need, but the screen title shifted to the right as there is an invisible back button text. And it definetly is (the root controller's title has 9 characters length):
The question is: How to change image, hide text and keep standart back action for every appearance of back button in ios 9.0 ?
There are three ways to do what you want.
I recommend: Create your own Navigation Class by extending and UINavigationController and override backbuttonItem (UIBarButtonItem) property to customise it according to your requirement. And use the same Navigation Controller class in your project.
Create a custom backBarButton by extending UIBarButtonItem and manually set the same as a back button of default Navigation Controller class, in all view controller.
Hide default navigation bar from root controller and create your own navigation bar using UIView and UIButton in all view controllers. (I always use this choice, that makes customization of navigation bar very easy for me. And I can set my view according to my requirement)
Here is how you can add Custom button for your navigation bar
let btnleft : UIButton = UIButton(frame: CGRect(x:0, y:0, width:35, height:35))
btnleft.contentMode = .center
btnleft.setImage(Set_Local_Image("arrow_left"), for: .normal)
btnleft.addTarget(self, action: #selector(YOUR_ACTION), for: .touchDown)
let backBarButon: UIBarButtonItem = UIBarButtonItem(customView: btnleft)
self.navigationItem.setLeftBarButtonItems([menuBarButon], animated:false)
instead of "arrow_left" You can use any image you want
For Default back action you can create function(YOUR_ACTION) and use in selector of back button
navController.popViewController(animated: true)
I can suggest you 2 options. Both require BaseViewController class as a superclass of all your view controllers.
If you are ok with native back button image, just want to remove back button text you can use this subclass:
class BaseViewController: UIViewController {
var navigationTitle: String = ""
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if !navigationTitle.isEmpty {
navigationItem.title = navigationTitle
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
navigationTitle = navigationItem.title ?? ""
navigationItem.title = ""
}
}
If you want to use your custom icon for back button, you should create UIBarButtonItem with your image, add target, selector, handle action of the button. Sample BaseViewController class below:
class BaseViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let backImage = UIImage(named: "arrow_left")
navigationItem.hidesBackButton = true
guard let navigationController = navigationController else {
return
}
if navigationController.viewControllers.count > 1 {
// we have to set back button only when we have at least 1 controller to go back
navigationItem.leftBarButtonItem = UIBarButtonItem(image: backImage, style: .plain, target: self, action: #selector(backBarButtonAction(sender:)))
}
}
// MARK: Actions
func backBarButtonAction(sender: UIBarButtonItem) {
navigationController?.popViewController(animated: true)
}
}
According to https://stackoverflow.com/a/16831482/5790492 there is a way to do this without appearance.
Swift 3.0
extension UIViewController {
func setupCustomBackButton() {
if let controllersCount = navigationController?.viewControllers.count, controllersCount > 1 {
let backButton = UIButton(frame: CGRect(x: 0, y: 0, width: 12, height: 20))
backButton.setBackgroundImage(UIImage(named: "arrow_left"), for: .normal)
backButton.contentMode = .left
let backButtonItem = UIBarButtonItem(customView: backButton)
backButton.addTarget(self, action: #selector(self.popCurrentViewController), for: .touchUpInside)
navigationItem.leftBarButtonItem = backButtonItem
navigationItem.hidesBackButton = true
}
}
func popCurrentViewController() {
navigationController?.popViewController(animated: true)
}
}
UINavigationBar.appearance().setBackgroundImage(UIImage(), for:
UIBarPosition.any, barMetrics: UIBarMetrics.default)
UINavigationBar.appearance().shadowImage = UIImage()
UINavigationBar.appearance().tintColor = UIColor.white
UINavigationBar.appearance().barTintColor = UIColor.main
UINavigationBar.appearance().isTranslucent = false
UINavigationBar.appearance().clipsToBounds = false
UINavigationBar.appearance().backgroundColor = UIColor.main
UINavigationBar.appearance().titleTextAttributes = [NSFontAttributeName :
(UIFont(name: "Helvetica", size: 18))!, NSForegroundColorAttributeName:
UIColor.white]
Try this code and make changes accordingly to set image, color and other properties
You should watch Mark Moeykens' youtube series on this. He is IMHO one of the best YouTube presenters for UI Design and implementation in Swift.
The play list is https://www.youtube.com/playlist?list=PLHDMmeIMXj8WyvlX5uFmppVn2Pm0bXVr7
Create an extension for UINavigationItem
extension UINavigationItem {
func backBarButtonItem() -> UINavigationItem {
return UIBarButtonItem(title: "", style: .Plain, target: nil, action: nil)
}
}
Currently I have 1 tab view controller, with 3 menus:
But when running, the bottom menu / image are like being cutted or didn't show perfectly like this:
It should have 3 menus.
Code:
import UIKit
class TabBarReimbursementViewController: UITabBarController{
var loadTable: Bool = false
override func viewWillAppear(animated: Bool) {
self.viewControllers![selectedIndex].viewWillAppear(true)
}
override func viewDidLoad() {
super.viewDidLoad()
// self.tabBar.barTintColor = UIColor.redColor()
self.tabBar.tintColor = UIColor.blackColor()
let addButton = UIBarButtonItem(barButtonSystemItem: .Add, target: self, action: #selector(TabBarReimbursementViewController.buttonClicked(_:)))
navigationItem.rightBarButtonItem = addButton
// UITabBarItem.appearance().setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.whiteColor() ], forState: .Normal)
UITabBarItem.appearance().setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.blackColor() ], forState: .Selected)
let historySelected: UIImage! = UIImage(named: "history2.png")?.imageWithRenderingMode(.AlwaysOriginal)
let approvalSelected: UIImage! = UIImage(named: "approve2.png")?.imageWithRenderingMode(.AlwaysOriginal)
let listSelected: UIImage! = UIImage(named: "listlist2.png")?.imageWithRenderingMode(.AlwaysOriginal)
(tabBar.items![1] ).selectedImage = historySelected
(tabBar.items![0] ).selectedImage = approvalSelected
(tabBar.items![2] ).selectedImage = listSelected
self.selectedViewController = self.viewControllers![1]
self.findHamburguerViewController()?.gestureEnabled = false
}
func buttonClicked(sender: UIBarButtonItem) {
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewControllerWithIdentifier("MyRequestForm") as! myRequestForm
nextViewController.formType = "New"
self.navigationController!.pushViewController(nextViewController, animated: true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
You CAPSPageMenu Library in which you can use tab bar controller very easily CAPSPageMenu
just add below code in Library
_menuScrollView.translatesAutoresizingMaskIntoConstraints = NO;
_menuScrollView.frame = CGRectMake(0.0, self.view.frame.size.width- _menuHeight,self.view.frame.size.width, _menuHeight);
The thing is that what you are doing is not how a tab bar controller's tab bar items work. Each child view controller (there are three of them in your storyboard screen shot) has its own tabBarItem, and that is how the tab bar gets populated.
For some reason, I have to add a UINavagationController() inside a UIViewController(), so I did the following in the view controller class:
class someViewController: UIViewController {
private let myNav = UINavigationController()
override func viewDidLoad() {
self.addChildViewController(myNav)
self.view.addSubview(myNav.view)
myNav.view.translatesAutoresizingMaskIntoConstraints = false
myNav.view.topAnchor.constraintEqualToAnchor(self.topLayoutGuide.bottomAnchor).active = true
myNav.view.leftAnchor.constraintEqualToAnchor(view.leftAnchor).active = true
myNav.view.rightAnchor.constraintEqualToAnchor(view.rightAnchor).active = true
myNav.view.heightAnchor.constraintEqualToAnchor(nil, constant: 44).active = true
myNav.didMoveToParentViewController(self)
}
}
The navigation controller is added & showing up correctly. Then I try to add a title (or Done button) to the navigation bar, however the items just don't show up. I tried a few things like this:
self.navigationItem.title = "some title"
myNav.navigationItem.title = "some title"
myNav.navigationItem.rightBarButtonItem = btnDone
What's the right way to do it in this case?
Why don't you use this simple code to add a navigation bar :
let navigationBar = UINavigationBar(frame: CGRectMake(0, 0, self.view.frame.size.width, 66)) // Offset by 20 pixels vertically to take the status bar into account
// Create a navigation item with a title
let navigationItem = UINavigationItem()
navigationItem.title = "Title"
// Create left and right button for navigation item
let leftButton = UIBarButtonItem(title: "Save", style: UIBarButtonItemStyle.Plain, target: self, action: "btn_clicked:")
let rightButton = UIBarButtonItem(title: "Right", style: UIBarButtonItemStyle.Plain, target: self, action: nil)
// Create two buttons for the navigation item
navigationItem.leftBarButtonItem = leftButton
navigationItem.rightBarButtonItem = rightButton
// Assign the navigation item to the navigation bar
navigationBar.items = [navigationItem]
// Make the navigation bar a subview of the current view controller
self.view.addSubview(navigationBar)
I have this app, which has profile page. I have mainview in storyboard, tableview, and profile view.
When I go to profile view I want to be able to go back to mainview so I try something like this
class ProfileViewController: UIViewController, UITextFieldDelegate, UINavigationBarDelegate{
var bar: UINavigationBar!
override func viewDidLoad(){
super.viewDidLoad()
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
bar = createBar();
}
func createBar() -> UINavigationBar{
let bar = UINavigationBar(frame: CGRectMake(0,0,self.view.frame.size.width,60))
bar.barTintColor = UIColor(red: 26/255, green: 53/255, blue: 72/255, alpha: 1.0)
bar.delegate = self
let navigationItem = UINavigationItem()
navigationItem.title = "Profile"
let leftButton = UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.Plain, target: self, action: "goBack:")
let rightButton = UIBarButtonItem(title: "Edit", style: UIBarButtonItemStyle.Plain,target: self, action: nil)
leftButton.tintColor = UIColor.whiteColor()
rightButton.tintColor = UIColor.whiteColor()
//bar.tittleTextAttributes = [UITextAttributeTextColor: UIColor.whiteColor()]
navigationItem.leftBarButtonItem = leftButton
navigationItem.rightBarButtonItem = rightButton
bar.items = [navigationItem]
self.view.addSubview(bar)
return bar;
}
func goBack(sender: UIBarButtonItem!){
if let navController = self.navigationController{
navController.popViewControllerAnimated(true)
}
}
}
I'm using SWRevealViewController.
Embed your Reveal View Controller in the UINavigationController.
Right now, the BackTable View Controller and the ProfileView Controller are not in Navigation Controller's hierarchy. Also, your segues should be push segues for this to work. Don't use modal segues.
Follow this simple tutorial for more clarity: http://code.tutsplus.com/tutorials/ios-from-scratch-with-swift-navigation-controllers-and-view-controller-hierarchies--cms-25462
First Embed RevealViewController in the UINavigation
navigationController!.popToViewController(navigationController!.viewControllers[0], animated: false)