iOS 13 - Custom back button without text Swift - ios

In my app, I have a custom icon for going back to previous ViewController.
It was working perfectly, but with iOS 13, the icon is misplaced.
The fun fact is that I still have to click on the left (where the back icon used to be, and in other words, on the blank space) to go back to previous ViewController.
Do you have any idea why?
Here is the code I use to customize the back button.
var back = UIImage(named: "backButton")
back = back?.withAlignmentRectInsets(UIEdgeInsetsMake(0, -50, 0, 50))
self.navigationController?.navigationBar.backIndicatorImage = back?.withAlignmentRectInsets(UIEdgeInsetsMake(0, -50, 0, 50))
self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = back?.withAlignmentRectInsets(UIEdgeInsetsMake(0, -50, 0, 50))
self.navigationController?.navigationBar.backItem?.backBarButtonItem = UIBarButtonItem(title: " ", style: UIBarButtonItemStyle.plain, target: nil, action: nil)
self.navigationController?.navigationBar.tintColor = .black
And this is a screenshot of the back icon, not on the left anymore:

Using UIBarButtonItem with customView suits well to your situation. By creating an instance of UIButton gives you command over choosing image and title both, besides custom selector can also be passed to handle button events.
Here is sample code:
let button = UIButton(type: .system)
button.setImage(UIImage(named: "YOUR IMAGE NAME"), for: .normal)
button.setTitle("TITLE IF ANY", for: .normal)
button.sizeToFit()
button.addTarget(self, action: #selector(backBtnPressed(sender:)), for: .touchUpInside)
let leftBtn = UIBarButtonItem(customView: button)
leftBtn.style = .plain
navigationItem.leftBarButtonItem = leftBtn
#objc func backBtnPressed(sender: UIBarButtonItem) {
print("BackBtnPressed")
}

Related

Making the nav bar title a button (Swift)

I'm trying to make the title of the nav bar its own button. Users in my app can have multiple profiles, and the nav bar title displays the username of their currently selected profile. Pressing this button should bring up a list of available profiles to choose from (handleShowProfiles). For some reason, the title displays but does not function as a button, it's just static text and touching it does nothing.
let changeProfileContainer : UIView = {
let container = UIView()
container.frame = CGRect(x: 0, y: 0, width: 200, height: 40)
let button = UIButton(type: .custom)
button.setTitle("#username ▼", for: .normal)
button.setTitleColor(.black, for: .normal)
button.frame = container.frame
button.addTarget(self, action: #selector(handleShowProfiles), for: .touchUpInside)
container.addSubview(button)
return container
}()
func configureNavBar() {
self.navigationController?.navigationBar.tintColor = .black
self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "send"), style: .plain, target: self, action: #selector(handleSubmitPost))
self.navigationItem.leftBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "drafts"), style: .plain, target: self, action: #selector(handleDrafts))
self.navigationItem.titleView = changeProfileContainer
}
Any ideas why the button part won't function? In Apple's documentation, it says you have to put the button inside a view, make the button type custom, and change the button's frame from it's default (0, 0, 0, 0). I'm pretty sure this is where I'm messing up but I dunno.
Linked to self invocations in computed property -- See the last portion of Ahmad F's answer
Don't know why, but selectors in computed properties don't seem to work.
I tried adding the container view without computing it and clicking on the button works.
func configureNavBar() {
self.navigationController?.navigationBar.tintColor = .black
let container = UIView()
container.frame = CGRect(x: 0, y: 0, width: 200, height: 40)
let button = UIButton(type: .custom)
button.setTitle("#username ▼", for: .normal)
button.setTitleColor(.black, for: .normal)
button.frame = container.frame
button.addTarget(self, action: #selector(pressTitle), for: .touchUpInside)
container.addSubview(button)
navigationItem.titleView = container
}

how to make the navigation button top left corner of the navigationbar

I have an programatically made nav button in navigation bar, I am trying to make image on the button(as like back button) and i made it, but my problem is, the button not appearing on the left corner, it appearing after some space.
let button = UIButton(type: .system)
button.frame = CGRect(x: 0, y: 0, width: 10, height: 40)
button.setTitle("Back", for: .normal)
button.setImage(UIImage(named: "ic_keyboard_arrow_left_2x"), for: .normal)
let barButton = UIBarButtonItem(customView: button)
self.navigationItem.leftBarButtonItems = [barButton]
please help me to acheive the task
Replace all code by :
self.navigationItem.backBarButtonItem = UIBarButtonItem(image: UIImage(named: "ic_keyboard_arrow_left_2x"), style: .plain, target: self, action: #selector(yourSelector))
self.navigationController?.navigationBar.topItem?.title = "Back"

Custom UIBarButtonItem With BG Colour and Text Swift 3

I have two buttons on my right of my navigation bar.
extension UIViewController {
func setNavigationBarItem() {
let profileButton = UIBarButtonItem(title: "?", style: .plain, target: self, action: #selector(didTapProfileButton(_:)))
navigationItem.rightBarButtonItems = [addRightBarButtonWithImage(UIImage(named: "menu")!), profileButton]
self.slideMenuController()?.removeRightGestures()
self.slideMenuController()?.addRightGestures()
}
}
I have created 2 buttons like this. But the profileButton I want is with background colour and having corner radius to that button. How to add it to make it look like :
Ignore black part. UIBarButton will be of yellow colour background and corner radius.
For that you have only one option you need to create UIButton instance with design that you want after that create UIBarButtonItem instance from that button.
let btnProfile = UIButton(frame: CGRect(x: 0, y: 0, width: 25, height: 25))
btnProfile.setTitle("SY", for: .normal)
btnProfile.backgroundColor = UIColor.yellow
btnProfile.layer.cornerRadius = 4.0
btnProfile.layer.masksToBounds = true
Now create the UIBarButtonItem from that button and set it with the rightBarButtonItems.
navigationItem.rightBarButtonItems = [addRightBarButtonWithImage(UIImage(named: "menu")!), UIBarButtonItem(customView: btnProfile)]
let profileButton = UIButton()
profileButton.frame = CGRect(x:0, y:0, width:30, height:30)
profileButton.setTitle("SY", for: .normal)
profileButton.setTitle("SY", for: .highlighted)
profileButton.backgroundColor = UIColor.yellow
profileButton.layer.cornerRadius = 5.0
profileButton.addTarget(self, action: #selector(didTapProfileButton(_:)), for: .touchUpInside)
let rightBarButton = UIBarButtonItem(customView: profileButton)
self.navigationItem.rightBarButtonItem = rightBarButton

how to change the navigation back item function ,back to rootView

I have a problem.
I use show(vc) to present a view controller.
vc1 --> vc2 --> vc3
I want to redirect user from vc1 when user clicks on back button on vc3, to achieve that I am using the below mentioned code.
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.hidesBackButton = true
let newBackButton = UIBarButtonItem(title: "<", style: UIBarButtonItemStyle.plain, target: self, action: #selector(backToRoot(sender:)))
self.navigationItem.leftBarButtonItem = newBackButton
}
func backToRoot(sender: UIBarButtonItem) {
_ = self.navigationController?.popToRootViewController(animated: true)
}
I want the default image of back button, not customized button.
Is there a way I can do that?
I just made this today. I found no way to change action of system back button. In order to look like the system style, I draw a same picture(snapshot the simulator, and change in photo shop). The code is as followed:
let button: UIButton = UIButton(type: .system)
the default size of height is 30, width is whatever you set
button.frame = CGRect(x: 0, y: 0, width: 80, height: 30)
button.setImage(UIImage(named: "BackButton"), for: .normal)
the default font is the following:
button.setTitle("Back", for: .normal)
button.titleLabel?.font = UIFont(name: "AvenirNext", size: 15)
This is the trick, you need find out the same position with the system's, the following is my result, I had adjusted many times. I hope you could use, but I think you need find your own size
button.imageEdgeInsets = UIEdgeInsetsMake(0, -43, 0, 0)
button.titleEdgeInsets = UIEdgeInsetsMake(0, -33, 0, 0)
button.addTarget(target, action: action, for: .touchUpInside)
let barButton = UIBarButtonItem(customView: button)

Cannot modify UIBarButton tintColor

I have a UIBarButton in my navigation bar, I set an image (silhouette.png) to it from the storyboard, and I can change that image's tint (color) at will:
if let num2 = Int(s, radix: 16) { //s="00ff00"
flamingoBtn.tintColor = UIColor(netHex:num2) //this btn is an IBoutlet
}
However, at some point I change the original image for another image (icon.png), programmatically, so I don't need to change the tint in this case, so far so good:
if let url = NSURL(string: "http://www.123di.com/CanonSGLens_132.png") {
if let data = NSData(contentsOfURL: url) {
var newImgThumb : UIImage=UIImage(data: data)!
var iconBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 35, height: 35))
iconBtn.setImage(newImgThumb, forState: UIControlState.Normal)
iconBtn.addTarget(self, action: "goToSettings:", forControlEvents: UIControlEvents.TouchUpInside)
var item = UIBarButtonItem(customView: iconBtn)
self.navigationItem.leftBarButtonItem = item
print("CUSTOM ICON: DOWNLOADED")
}
}
The problem comes, when I switch to the icon image to the original silhouette.png, because I cannot modify the tint any longer, it remains always blue silhoute (default color), instead of green, red, etc:
var newImgThumb : UIImage=UIImage(named: "happyface.png")!
var replyBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 35, height: 35))
replyBtn.setImage(newImgThumb, forState: UIControlState.Normal)
replyBtn.addTarget(self, action: "goToSettings:", forControlEvents: UIControlEvents.TouchUpInside)
replyBtn.tintColor = UIColor.greenColor()
var item = UIBarButtonItem(customView: replyBtn)
item.tintColor = UIColor.greenColor()//UIColor(netHex:num2)
self.navigationItem.leftBarButtonItem = item
What am I doing wrong, why are tint changes igonred afterwards??
If you need extra details let me know.
If you google how to set the custom image for your bar button, pretty much everyone will tell you create a UIButton and then create the UIBarButtonItem from the UIButton as a customView:. In which case, you are doing the right thing here.
However, if you create the UIBarButtonItem via cutomView:, you are not able to change the tintColor any more. And this following is how you set custom image and also changing the tintColor
let item = UIBarButtonItem.init(image: UIImage(named: "happyface.png")!,
style: .Plain,
target: self,
action: Selector("goToSettings:"))
item.tintColor = UIColor.greenColor()
self.navigationItem.leftBarButtonItem = item
Depending where are you calling the code above, you might need to put it inside this structure, to make it run in the UI thread and make the change visible:
dispatch_async(dispatch_get_main_queue()) {
//code here
}
In case someone is still looking for the solution.
barButtonItem.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.red], for: .normal)
By setting the NSAttributedString.Key.foregroundColor of the title text attributes, you can set the color of the button.
If you follow this way you can do whatever you need.
let logoutNavBarButtonItem = UIBarButtonItem.init(
image: imageName,
style: .plain,
target: self,
action: #selector(buttonPressed))
navigationItem.leftBarButtonItem = logoutNavBarButtonItem

Resources