When attempting to place a UIImageView(UIImage) into a UIBarButtonItem on a UINavigationBar, the image gets placed in the middle of the bar and also has wide fields covering the entire bar. So, doesn't look like a small button on the left.
I've tried various tricks with frame resizing, contentMode settings.
The below code is from my View Controller, which is part of the Navigation Controller stack. Added this image into Assets:
http://pluspng.com/img-png/png-hd-bike-ktm-bike-png-500.png
for testing, named it bike.png and used it in UIImage below.
override func viewDidLoad() {
super.viewDidLoad()
let image = UIImage(named: "bike")
let imageView = UIImageView(image: image)
imageView.backgroundColor = .blue //for debugging
imageView.contentMode = .scaleAspectFit
navigationItem.leftBarButtonItem = UIBarButtonItem(customView: imageView)
}
The expected result would be to have the image of the motorbike in the left, rather than in the middle. Also, no empty fields to the left and to the right (highlighted in blue for debugging) of the image.
EXPECTED (drew up in Paintbrush):
REALITY:
Ended up resolving as:
imageView.widthAnchor.constraint(equalToConstant: (navigationController?.navigationBar.frame.height)!).isActive = true
Related
I have this view hierarchy on a view embedded in a UINavigationController:
When I scroll the UITableView the navigation bar is not moving up (the title is not becoming smaller) it stays like this:
If I remove the image view as background view everything works well.
My navigation is configured like this:
navigationItem.title = "Title here"
navigationItem.largeTitleDisplayMode = .always
navigationController?.navigationBar.prefersLargeTitles = true
navigationController?.navigationBar.shadowImage = UIImage()
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.isTranslucent = true
navigationController?.navigationBar.tintColor = .white
navigationController?.navigationBar.barStyle = UIBarStyle.blackTranslucent
navigationController?.navigationBar.backgroundColor = .clear
A project demonstrating the problem is available here:
https://drive.google.com/file/d/181Aggala2ZfGN0lDjEtHWg0vobkM0iJc/view?usp=sharing
I already tried to change the insets of the tableview but it didn't work.
tableView.contentInset = UIEdgeInsets(top: navigationController?.navigationBar.height, left: 0, bottom: 0, right: 0)
Thanks!
As you discovered, to make large title fonts work as you want them to, the UIScrollView or any of its subclass needs to be the first element in the view hierarchy.
To fix your problem, you can try setting the background image to be the background of the UITableView directly.
Edit: Okay soo according to your comment you want a background behind everything including navigation bar. There is one way of achieving this and that is to subclass your UINavigationController and inside viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
let image = UIImage(named: "wallpaper")
let imageView = UIImageView(image: image)
imageView.contentMode = .scaleAspectFill
imageView.frame = UIScreen.main.bounds
//this below part is important. Make sure to set it to 0 otherwise it will cover everything else
view.insertSubview(imageView, at: 0)
}
And then make sure your UIViewController containing the UITableView has a clear color for the UIView and remove the background image from that UIViewController
I have this navigation bar I am trying to implement that looks like this:
I know I can either put the image directly in the nav bar or as a header image below it, but I have no idea how to inset it so that it is contained in both the main container view and breaching the navigation bar as well.
Any ideas would be helpful!
I guess it's achievable using two images:
background: will match the navigation bar frame
icon: let's say an image 50x50 centered to the background in x-axis and y-axis with offset of its height / 2.0
Then you may try to use autolayout constraints doing so:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
guard let navbar = self.navigationController?.navigationBar else {return} // be sure to have defined a navigation controller
navbar.clipsToBounds = false // so the icon will be visible outside the nav bar
let niceBkg = UIImageView(image: UIImage(named: "bkg"))
navbar.addSubview(niceBkg)
niceBkg.translatesAutoresizingMaskIntoConstraints = false
niceBkg.leftAnchor.constraint(equalTo: navbar.leftAnchor).isActive = true
niceBkg.rightAnchor.constraint(equalTo: navbar.rightAnchor).isActive = true
niceBkg.topAnchor.constraint(equalTo: self.navigationController!.view.topAnchor).isActive = true
niceBkg.bottomAnchor.constraint(equalTo: navbar.bottomAnchor).isActive = true
let niceIcon = UIImageView(image: UIImage(named: "icon"))
niceBkg.addSubview(niceIcon)
niceIcon.translatesAutoresizingMaskIntoConstraints = false
niceIcon.widthAnchor.constraint(equalToConstant: 50).isActive = true
niceIcon.heightAnchor.constraint(equalToConstant: 50).isActive = true
niceIcon.centerXAnchor.constraint(lessThanOrEqualTo: niceBkg.centerXAnchor).isActive = true
niceIcon.bottomAnchor.constraint(greaterThanOrEqualTo: niceBkg.bottomAnchor, constant: 25).isActive = true
}
}
on iPhoneX the result is:
About your scenario, you probably need only the icon and a navigationBar with a proper background color. However I added both autolayout configurations because might be useful for someone else, especially if the navigationBar's background is quite complex with border, decorations and so on.
I have a logo that appear on top of all my UIViewController(controlled by NavigationController).
When I get the transition between UIViewController, the logo also swipe.
What I want: I want to logo(60 pixel height) to always stay. And the swipe transition to appear below the logo.
I've tried this in view delegate, but the logo also swipe :(
let logo = UIImage(named: "logo.png")
let imageView =UIImageView(image:logo)
self.navigationItem.titleView = imageView
Issue: You have the logo swiping when transiting to next VC.
Desired Result: You want to have the logo show up on each VC without the swipe animation. But still have the Swipe animation running for everything below the logo.
What I would do is make a UIScrollView and keep the logo as just a UIImageView.
If you have github repo of this app I can take a look for you.
Subclass the UINavigationController and in the viewDidLoad, configure the logo image view and add it to the navigationBar as a subview. Also, since we're adding it to the navigation bar which is only 44px in height, so a logo with a height of 60px would overflow the bounds.
class NavigationController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
let logo = UIImage(named: "logo.png")!
let imageView = UIImageView(image: logo)
let width = logo.size.width * 60 / logo.size.height
imageView.contentMode = .scaleAspectFit
imageView.frame.size = CGSize(width: width, height: 60)
imageView.center = navigationBar.convert(navigationBar.center, to: navigationBar)
navigationBar.addSubview(imageView)
}
}
I am trying to put a logo (png) file into my navigation controller. I found one solution that "worked" but it didn't scale down the image to fit, thus is was massive
This is the code im using thus far, but it makes the image huge
let logoImage:UIImage = UIImage(named: "logo.png")!
self.navigationItem.titleView = UIImageView(image: logoImage)
Try this:
let logo = UIImage(named: "logo.png")
let imageView = UIImageView(image:logo)
imageView.contentMode = UIViewContentMode.ScaleAspectFit //you need to set this.
self.navigationItem.titleView = imageView
And if you want to give height and width then add this:
imageView.frame.size.width = 200
imageView.frame.size.height = 45
You can do it in 2 ways: programmatically or via XCode:
An easy way is via XCode. For it, drag view from the object library and drag it to your navigation bar. Later drag into your view in navigation bar UIImageView from object library. That's all.
Or you can do all of this programmatically.
var myView = UIView()
var imageView = UIImageView()
imageView.image = UIImage(named: "your_image_here")
myView.addSubview(imageView)
navigationController?.navigationBar.addSubview(myView)
Hi I am making an app with a background that leaves a big blank white space at the top of the screen when I use the first code shown below and as soon as I add self.view.addSubview(image view) at the end of this code like the second piece of code it covers all my labels and buttons, how can I have it so that it takes up the whole screen like in the second part but doesn't cover up the buttons like in the first piece of code?
thanks !
first code
override func viewDidLoad() {
super.viewDidLoad()
let yourImage = UIImage(named: "fond320x480.png")
let imageview = UIImageView(image: yourImage)
self.view.addSubview(imageview)
self.view.sendSubviewToBack(imageview)
imageview.contentMode = UIViewContentMode.ScaleToFill
imageview.contentMode = UIViewContentMode.ScaleAspectFill
imageview.frame = self.view.bounds
second code:
override func viewDidLoad() {
super.viewDidLoad()
let yourImage = UIImage(named: "fond320x480.png")
let imageview = UIImageView(image: yourImage)
self.view.addSubview(imageview)
self.view.sendSubviewToBack(imageview)
imageview.contentMode = UIViewContentMode.ScaleToFill
imageview.contentMode = UIViewContentMode.ScaleAspectFill
imageview.frame = self.view.bounds
self.view.addSubview(imageview)
try to send it to the back using this method
insertSubview:yourSubView atIndex:0
and give it the index by zero.
or use this one
-insertSubview:aboveSubview:
the other solution is to add all your view in one view and then add the image and use method -belowSubView- to add the image under the view that has all your views
hope this answer can help good luck