In our app we are showing a burger item in the UINavigationBar.
We are using the leftBarButtonItem as the place to show it.
Here is the code to create the burger button.
let barItem = UIBarButtonItem(image: UIImage(named: "IconBurger"), style: .plain, target: target, action: selector)
barItem.tintColor = .tintColor
barItem.adjustAccessibility()
Which leads to following result on iOS 11.4 and iOS 11.3.1
iOS11.4
iOS10.3.1
As you can see the burger button somehow shrinked on iOS11.4
I fixed this by creating a custom button view like this:
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "IconBurger"), for: .normal)
button.addTarget(target, action: selector, for: .touchUpInside)
let barItem = UIBarButtonItem(customView: button)
barItem.tintColor = .tintColor
barItem.adjustAccessibility()
Using this version the burger button is looking good on iOS 11.4 again.
But now when going back to 10.3.1 I was shocked because the burger button was not rendered at all anymore.
(Imagine completely black image here)
I ended up writing ugly stuff like
if #available(iOS 11.4, *) {
// show new version
} else {
// show old version
}
But I hope that can't be it!
Does anybody experienced similar or can give advise ?
Additional information: We are using pdf assets for creating UIImages in our project.
Ok. Colleague of mine found the solution which I want to document here.
Turns out calling sizeToFit() was missing on < iOS11
let button = UIButton(type: .custom)
let image = UIImage(named: "IconBurger")
button.setImage(image, for: .normal)
button.addTarget(target, action: selector, for: .touchUpInside)
button.sizeToFit()
let item = UIBarButtonItem(customView: button)
item.adjustAccessibility()
return item
Related
I created the SwipingController app.
The application was supposed to have the functionality of scrolling with gestures and a management bar with 2 buttons and UIPageControl.
For now, these buttons were supposed to print only a text message in the console, but it doesn't.
let nextButton: UIButton = {
let button = UIButton(type: .system)
button.setTitle("NEXT", for: .normal)
button.setTitleColor(.black, for: .normal)
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 14)
button.addTarget(self, action: #selector(handleNextButton), for: .touchUpInside)
return button
}()
#objc func handleNextButton() {
print("Next Botton Pressed")
}
I wanted to add the whole page management bar in a separate file.
When it goes to the main controller, the whole functionality work.
I don't want to paste all the code, so it gives a link to the git
https://github.com/SebaKrk/SwipingControllerProgrammatic.git
Picture from simulator
The Problem is that you set your target right in the setup code of your UIButton
let previousBotton : UIButton = {
let button = UIButton(type: .system)
button.setTitle("PREV", for: .normal)
button.setTitleColor(.black, for: .normal)
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 14)
button.addTarget(self, action: #selector(handlePreviousButton), for: .touchUpInside)
return button
}()
It seems like the self is not initialized at this point. Because this code is run before your init was run.
So you have to set the target of the Button after you called super.init then it works.
I'm using a UICollectionViewCompositionalLayout with a search controller:
just like this
The Problem:
I can't tap on the UI Button present in the header of Section when the search controller is active. But the GestureRecognizer of the Section just works fine.
Both of them works when I'm not searching anything, and if a tap "enter" on keyboard while searching, the button start to work.
What I'm doing wrong?
I just found an solution. For those who are having problem:
I was adding the Target this way
let button: UIButton = {
let button = UIButton(type: .custom)
button.setTitle("See all", for: .normal)
button.setImage(UIImage(systemName: "chevron.right", withConfiguration: buttonConfig), for: .normal)
button.addTarget(self, action: #selector(myFunc), for: .touchUpInside)
return button
}()
Removing the addTarget, and adding it on the Init of the class fixes the Problem.
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(button.addTarget)
button.addTarget(self, action: #selector(myFunc), for: .touchUpInside)
}
I Don't know why, but it works. lol
I am building an e-commerce application that has shopping cart in rightBarButtonItem.I have implemented extension to add shopping cart barButtonItem in every UIViewControllers.My barButtonItem is showing properly in simulator devices ( including iPhone 6s,iPhone SE and iPhoneX simulators ).But it is not showing on my physical device ,iPhone 6s.Could anyone help me how to trace this issue?? Thanks for your attention
Here is my code
extension UIViewController{
func addCartBarButtonItem(){
let cartButton = UIButton(type: .custom)
cartButton.setImage(UIImage(named:"cart"), for: .normal)
cartButton.widthAnchor.constraint(equalToConstant: 28.0).isActive = true
cartButton.heightAnchor.constraint(equalToConstant: 28.0).isActive = true
cartButton.addTarget(self, action: #selector(self.goCheckOutController), for: .touchUpInside)
let cartBarButtonItem = UIBarButtonItem(customView: cartButton)
cartBarButtonItem.addBadge(number: CartDataManager.loadItems().count)
self.navigationItem.rightBarButtonItem = cartBarButtonItem
}
}
Try this,
var rightSearchBarButtonItem : UIBarButtonItem?
func addCartButtonToNavigationBar(){
self.rightSearchBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "cart") , style: UIBarButtonItemStyle.plain, target: self, action: #selector(goCheckOutController))
self.navigationItem.rightBarButtonItem = self.rightSearchBarButtonItem;
}
This code is working for me
I'd like to be able to change only the text color of the back button in the navigation bar.
As a work around, I can sort of do what I'm trying to do by creating a custom view and assigning it to navigationItem.leftBarButtonItem, but it doesn't look very good and I also lose the swipe to pop ability.
Code for the above:
let button = UIButton(type: .system)
let originalImage = #imageLiteral(resourceName: "BackButton")
let scaledImage: UIImage = UIImage(cgImage: originalImage.cgImage!, scale: 30, orientation: originalImage.imageOrientation)
button.setImage(scaledImage, for: .normal)
button.setTitle("YourTitle", for: .normal)
button.sizeToFit()
button.setTitleColor(.brown, for: .normal)
button.tintColor = .blue
navigationItem.leftBarButtonItem = UIBarButtonItem(customView: button)
I also see things suggested like setting attributes of the back button via
navigationController?.navigationBar.topItem.backBarButtonItem?.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.red], for: .normal)
but that doesn't seem to have any effect on the look of the text, despite
print("Attributes: ", navigationController?.navigationBar.topItem?.backBarButtonItem?.titleTextAttributes(for: .normal) ?? "No attributes")
resulting in Attributes: ["NSColor": UIExtendedSRGBColorSpace 1 0 0 1].
I could set tintColor but that would change the color of the back icon in addition to the title.
So what's the best way to do what I want? Is there a way?
Am not sure whether I understood you correctly. But try the below code. This will apply to all the bar button items of your app. Place this code where it is called only once though out app lifecycle. Like application: didFinishLaunchingWithOptions:
let attribs = [NSForegroundColorAttributeName: UIColor.red, NSFontAttributeName: UIFont.boldSystemFont(ofSize: 18)]
UIBarButtonItem.appearance().setTitleTextAttributes(attribs, for: .normal)
I figured it out. You can style the back button by setting self.navigationItem.backBarButtonItem in the previous view controller.
For example, in my case I had TableViewController and when you clicked on a cell, the app would transition to ViewController. In TableViewController I had
public func changeColor() {
let barButton = UIBarButtonItem(title: "Anything", style: .plain, target: nil, action: nil)
barButton.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.brown], for: .normal)
self.navigationItem.backBarButtonItem = barButton
}
and then in ViewController I had
#IBAction func buttonPressed(_ sender: Any) {
let vc = self.navigationController?.viewControllers[0] as! TableViewController
vc.changeColor()
self.title = "hello very long title asdfasdfasfdasdfasdfasdfasdfasdf"
}
As a result, pressing a button in ViewController would change the color of the title of its back button to brown.
I want to change the image of a UIButton for different states. To achieve this, I'm using:
btn.setImage(UIImage(named: "blabla"), for .normal)
and
btn.setImage(UIImage(named: blabla2), for .disabled)
This only makes some appear dimmed.
What did I do wrong? I just want to make my button appearance the same for different states, how?
(my button type - .system).
This helped me (swift 3.0)
btn.setImage(UIImage(named:"yourFriend")?.withRenderingMode(.alwaysOriginal), for: .normal)
btn.setImage(UIImage(named:"yourFriend")?.withRenderingMode(.alwaysOriginal), for: .disabled)
You just need to set one for the state. And if you don't set another image for different state. It would look the same in all state.
button.setImage(image, forState: .Normal)
How to change UIButton image in Swift
For display disabled button set image
let btn = UIButton(type: .Custom)
btn.setImage(UIImage(named: blabla2), for .disabled)
Then
btn.enabled = false // to display Disable image
btn.enabled = true // to display Normal image
private let button1: UIButton = {
let button = UIButton(type: .custom)
button.setImage(UIImage(named:"firstButtonNormalStateImage"), for: .normal)
button.setImagesetImage(UIImage(named:"firstButtonSelectedStateImage"), for: .selected)
return button
}()
private let button2: UIButton = {
let button = UIButton(type: .custom)
button.setImage(UIImage(named:"secondButtonNormalStateImage"), for: .normal)
button.setImage(UIImage(named:"secondButtonSelectedStateImage"), for: .selected)
return button
}()
// implement for example in viewDidLoad()
button1.addTarget(self, action: #selector(firstButtonDidTap), for: .touchUpInside)
button2.addTarget(self, action: #selector(secondButtonDidTap), for: .touchUpInside)
// trigger actions
#objc func firstButtonDidTap() {
button1.isSelected = true
button2.isSelected = false
}
#objc func secondButtonDidTap() {
button2.isSelected = true
button1.isSelected = false
}
For whoever is still having this issue (currently Xcode 10.0) with a Custom button, I found I was able to change the text and/or image if instead of:
myButton.setTitle("Hi", for: [.normal])
I used this:
myButton.setTitle("Hi", for: []) //remove specific states
I don't know why .normal was not working for me, even though the button was definitely enabled. But maybe this will save someone else a headache!
You can simply do this by StoryBoard as well.
Select the button, got to identity inspector and do the following:-
Firstly set the buttonType to custom instead of system.
Secondly choose state Config to lets say default and give the imageName in "image" attribute, similarly choose other state configs (Highlighted, disabled, selected etc.) and set images as required by you.
Then later in the code you just have to control and set the state of the button, and respective image will be shown to you.