Getting the position of my UIBarButtonItem in iOS 11 - ios

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:.

Related

How to constrain navigation buttons all the way to the left or right? (iOS)

I am trying to align the navigation bar buttons all the way to the right and left because there is some space between the edge of the screen and the buttons. Any ideas how to constrain the leading anchor of the button to the leading edge of the navigation bar/screen?
When adding navigation items, you do not need to set constraints, but rather, frames.
I've experienced your issue and currently experiencing it on iOS 11. A quick solution that I use is to add a clear negative spacer bar button. Like so:
internal lazy var button_Skip: UIButton = {
let button = UIButton(type: .custom)
button.setup("SKIP".localized(), normalTextColor: .blue)
button.isHidden = true
return button
}()
let barButton = UIBarButtonItem(customView: self.button_Skip)
self.button_Skip.frame = CGRect(x: 0, y: 0, width: 55.0, height: 44.0)
let negativeSpacer = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.fixedSpace, target: nil, action: nil)
if #available(iOS 11.0, *) {
negativeSpacer.width = -10.0
}
I hope this helps.

UIBarButtonItem with custom UIButton is invisible on iOS <= 10

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.

Custom bar button item not sizing properly

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.

Adding a custom navigation bar covering content in screen

I have added a custom navigation bar via storyboard. I was expecting the content on the screen to automatically shift downward. but instead it completely covers content on the top of the screen.. is there a clean line of code that automatically creates that spacing between the navigation bar and the view itself?
You might have heard about Cocpods which i feel is a better way to go for cutsom Navigation bar.
You just need to implement the protocol and give the specifications you need for the Navigation bar
Go through the following cooped
https://cocoapods.org/pods/resizable-navigation-bar
Just call this method from viewDidLoad :
func createNavBar() {
let leftNavigationButton = UIButton()
leftNavigationButton.setImage(UIImage(named: "ic_back.png"), forState: .Normal)
leftNavigationButton.frame = CGRectMake(10, 10, 20, 15)
leftNavigationButton.addTarget(self, action: "onBackButtonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
let customBarItem = UIBarButtonItem(customView: leftNavigationButton)
self.navigationItem.leftBarButtonItem = customBarItem;
//set TitleAppIcon
let GR = UITapGestureRecognizer(target: self, action: Selector("headerLogoTapAction:"))
let imageView = UIImageView(frame: CGRect(x: 90, y: 0, width: ((UIScreen.mainScreen().bounds.width)/3), height: 40))
imageView.contentMode = .ScaleAspectFit
let image = UIImage(named: "yourimag.png") //or set title
imageView.image = image
imageView.addGestureRecognizer(GR)
imageView.userInteractionEnabled = true
navigationItem.titleView = imageView
}
Hope this gonna help you

Putting imageview on navigation bar

I want to add image to right side of navigation bar. But I can't drag image view to navigation bar. I can only drag a button.
How can I do this ? I want same thing with whatsapp profile image. You know they have circle profile picture on right side of navigation bar.
Drag a UIView and drop it on the navigation bar first. Then drag a UIImageView into the view.
That should give you what you are looking for.
Set the image view height and width using constraints. You have to set the width and height of the containing view in the size inspector.
**This will Display the image on right side on navigation bar**
func viewDidLoad(){
let containView = UIView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
let imageview = UIImageView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
imageview.image = UIImage(named: "photo.jpg")
imageview.contentMode = UIViewContentMode.scaleAspectFit
imageview.layer.cornerRadius = 20
imageview.layer.masksToBounds = true
containView.addSubview(imageview)
let rightBarButton = UIBarButtonItem(customView: containView)
self.navigationItem.rightBarButtonItem = rightBarButton
}
Don't know about storyboards. But from code you can create UIBarButtonItem with custom view.
let customView = UIImageView()
let customViewItem = UIBarButtonItem(customView: customView)
self.navigationItem.rightBarButtonItem = customViewItem
From storyboard:
Just drag UIBarButtonItem into your controller navigation bar. In element menu(Attribute inspector) select identifier: Custom and Image: the image you want.

Resources