I need to create a "burger menu" button for my app on my navigationController's left side but since the NavCon is transparent I need to have a shadow on my icon.
Thus I've created a custom UIButton with an image, a drop shadow and the added it as a custom view on a UIBarButtonItem as follows:
let menuButton = UIButton(type: .custom)
menuButton.addTarget(self, action: #selector(showSideMenu), for: .touchUpInside)
menuButton.setImage(#imageLiteral(resourceName: "menu_white"), for: .normal)
menuButton.tintColor = UIColor.white
menuButton.layer.masksToBounds = false
menuButton.layer.shadowColor = UIColor.black.cgColor
menuButton.layer.shadowOpacity = 1.0
menuButton.layer.shadowRadius = 5
menuButton.layer.shadowOffset = CGSize(width: 0.0, height: 1.0)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: menuButton)
The code above works perfectly fine on iOS 11, but when I tested my app on ios 9 and 10 (both simulators and real devices) the menu icon is invisible. It is clickable and works as expected, but there is no visible icon.
In the View Hierarchy Debugger I can see a UIButton with 0 width and height, while in ios 11 I can see the normal UIButtonBarStackview with the embedded UIButton.
Any ideas on how to fix this and why this is happening? Thank you very much!
Please mention the button frame
let menuButton = UIButton(frame: CGRect(x: 0, y: 0, width: 70, height: 40))
It may helps to you thank you
You can just call menuButton.sizeToFit() and it will work.
Related
On App Start, I highlight one of my BarButtonItems. Since iOS11 I am not able to do this anymore because I need to initialise it on another way.
First my old ios 10 code. I saved my barButtonItemView after initialising it.
let item1 = UIBarButtonItem(image: UIImage(named: "iconProfile"), style: .plain, target: self, action: #selector(pushSettings))
self.navigationItem.setRightBarButtonItems([item1], animated: true)
if let view = self.navigationItem.rightBarButtonItem?.value(forKey: "view") as? UIView {
barButtonItemView = view
}
Now I was able to access the position of barButtonItem just by using the frame
barButtonItemView.frame.topMiddle.x
With ios 11 the picture on my UIBarButtonItem gets smaller. I was reading that I have to resize them by using constraints. So now I initialise my UIBarButtons by using this function:
let imageView = UIImageView(image: UIImage(named: imageName))
imageView.frame = CGRect(x: 5, y: 7, width: 20, height: 20)
let button = UIButton()
button.frame = CGRect(x: 0, y: 0, width: 30, height: 34)
button.addTarget(self, action: action, for: .touchUpInside)
button.widthAnchor.constraint(equalToConstant: 30).isActive = true
button.heightAnchor.constraint(equalToConstant: 34).isActive = true
button.addSubview(imageView)
let barItem = UIBarButtonItem(customView: button)
return barItem
I set my rightBarButtonItem on the same way and try to get the view on the same way.
self.navigationItem.setRightBarButtonItems([item1], animated: true)
if let view = self.navigationItem.rightBarButtonItem?.value(forKey: "view") as? UIView {
barButtonItemView = view
}
But this time my barButtonItemView has the x and y values set to 0,0. Has anyone an idea how I can get the position of my BarButtonItem depending on my screen?
What I tried
The first solution I tried is to call layoutIfNeeded() before I try to get the frame again. This is not working as well as the x and y values are still 0,0.
First, if your UIBarButtonItem only needs to display an UIImage, you should use [UIBarButtonItem initWithImage:style:target:action:] instead of customView for more standard layout. And if you want to custom the size of UIBarButtonItem, you can resize the image.
Second, before iOS 10, UIBarButtonItem's view was added in the UINavigationBar directly, but after iOS 11, UIBarButtonItem was added in a UIStackView, and the stackView was added in the UINavigationBar, so if you get a (0, 0) from the customView's frame.origin, it means that the customView is layout at the (0, 0) origin in the stackView.
Third, the view of the UIBarButtonItem would not be initialized until the UINavigationBar was shown and your UIBarButtonItem was put in the bar, so you can not get the view when the UIBarButtonItem just be initialized. Maybe you can try to get the view and its frame in your viewController's viewWillAppear: or viewDidAppear:.
I am completely new to iOS development and I am supposed to fix some bugs in an iOS app which is made using Swift 3.0 and Xcode 8 and it works almost fine. But when I open it with Xcode 9 and Swift 4.0 it shows some buttons way different that they were before.
Here is the source code for one of those buttons.
let button: UIButton = UIButton.init(type: UIButtonType.custom)
//set image for button
button.setImage(UIImage(named: "menu.png"), for: UIControlState())
button.frame = CGRect(x: 0, y: 0, width: 30, height: 23)
let barButton = UIBarButtonItem(customView: button)
button.addTarget(self, action: #selector(ViewController.shareButtonPressed), for: UIControlEvents.touchUpInside)
self.navigationItem.leftBarButtonItem = barButton
this code is inside the ViewDidLoad method. My problem is when I remove,
button.setImage(UIImage(named: "menu.png"), for: UIControlState())
it disappears the button but when I change the height and the width from,
button.frame = CGRect(x: 0, y: 0, width: 30, height: 23)
it changes nothing.
My problem is how can I fix this bug. Any suggestion, answer is highly appreciated and if the given details are not enough, please mention. Thank you!
Beginning with iOS 11, views added to toolbars using UIBarButtonItem using UIBarButtonItem(customView:) are now laid out using auto layout. You should add sizing constraints on your button. For example:
button.widthAnchor.constraintEqualToConstant(30.0).isActive = true
button.heightAnchor.constraintEqualToConstant(23.0).isActive = true
Otherwise, auto layout will use the intrinsic content size of your header view which is likely not what you expect.
For more information see the WWDC 2017 session Updating your app for iOS 11.
swift 4:
button.widthAnchor.constraint(equalToConstant: 30.0).isActive = true
button.heightAnchor.constraint(equalToConstant: 20.0).isActive = true
You can customize width and height of button using storyboard in Xcode. Just select your button and open this window.
After that just add the height constraints.
I have a custom app that includes a custom bar button item, with Swift 3 it was sized appropriately but after updating to Swift 4 it is no longer sizing to the constraints provided. This is my code:
let infoButton = UIButton.init(type: .custom)
infoButton.setImage(UIImage(named: "info button white.png"), for: UIControlState.normal)
infoButton.addTarget(self, action: #selector(StartViewController.infoButtonPressed), for: UIControlEvents.touchUpInside)
infoButton.frame = CGRect(x: 0, y: 0, width: 25, height: 25)
let barButton = UIBarButtonItem(customView: infoButton)
self.navigationItem.rightBarButtonItem = barButton
I tried changing the CGRect numbers to see if there would be any change, and there is not, it is sizing to the limits of the navigation bar, and frankly now looks quite ugly.
Any ideas about what changed in Swift 4? I am running Xcode 9.0(9A235)
Try setting constraints like this:
infoButton.widthAnchor.constraint(equalToConstant: 25).isActive = true
infoButton.heightAnchor.constraint(equalToConstant: 25).isActive = true
Or use images of the correct size.
I'm trying to get a button with an icon to the left of some text:
Having trouble with my understanding of UIButton. Adding a title to the button works fine:
import UIKit
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 300, height: 25))
button.backgroundColor = .green
button.contentHorizontalAlignment = .left
button.contentVerticalAlignment = .fill
button.titleLabel!.backgroundColor = .blue
button.setTitle("639", for: .normal)
button.setTitleColor(.white, for: .normal)
but then when you add an image
button.setImage(UIImage(named: "test"), for: .normal)
button.imageView!.backgroundColor = .clear
button.imageView!.contentMode = .scaleAspectFit
it keeps it's original size (300px) and pushes the title out the right side out of the buttons bounds. (can't see it in screenshot as its only showing button frame)
What am I doing wrong? Why does the image retain it's original width even though its been scaled down? What does contentHorizontalAlignment even do if it allows items to be pushed out of frame?
I'm aware that you can set insets but this is being used in a re-useable view so I can't hardcode values.
Thanks for the help
I just made a button just like what you said.
By the way why don't you use inset.Apple has given us the opportunity to use this.Then why shouldn't we use this?
Note: You have to make trial and error to position the image and text correctly.
Autolayout:
And inset:
If it's not accurate i said you have to make trial and error. happy coding. :)
I'm trying to add a UiButton on top of googleMapView.
I want to have a another button to open my Google Maps app for navigation from my app.
I tried adding a button programmatically and using xib.. its not working in both ways. (not showing).
Do you guys have any idea about it. I'm using swift
try adding the button as a subview.
create the button like this:
let button = UIButton()
button.backgroundColor = .blue
button.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 50)
button.setTitle("My Button", for: .normal)
and add it as a subview to your googleMapView like this:
googleMapView.addSubview(button)