Hi I'm working on an iOS Swift project in which I want to show users profile picture in the navigation bar as rounded. I tried lot of sample code, but it is not making rounded curve. Please help me.
I have tried these codes,
var image = UIImage()
if let userImage = UserProfile.image {
let imageUrl = self.dmcCommon.convertStringToImageURL(url: userImage)
let data = (try? Data(contentsOf: imageUrl as URL))!
image = UIImage(data: data)!
} else {
image = UIImage(named: "Me")!
}
let v = UIImageView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
v.image = image
v.layer.masksToBounds = true
v.layer.cornerRadius = 20
let rightBtn = UIBarButtonItem(customView: v)
self.navigationItem.rightBarButtonItem = rightBtn
And the result is like this,
Here the image is not getting round also it taking full width not as I gave.
Later I tried another solution, which is,
let button = UIButton()
button.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
var image = UIImage()
if let userImage = UserProfile.image {
let imageUrl = self.dmcCommon.convertStringToImageURL(url: userImage)
let data = (try? Data(contentsOf: imageUrl as URL))!
image = UIImage(data: data)!
} else {
image = UIImage(named: "Me")!
}
UIGraphicsBeginImageContextWithOptions(button.frame.size, false, image.scale)
let rect = CGRect(x:0, y:0, width:button.frame.size.width, height:button.frame.size.height)
UIBezierPath(roundedRect: rect, cornerRadius: rect.width/2).addClip()
image.draw(in: rect)
let newImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
button.addTarget(self, action:#selector(self.navToMe), for: UIControl.Event.touchUpInside)
let color = UIColor(patternImage: newImage)
button.backgroundColor = color
button.layer.cornerRadius = 0.5 * button.bounds.size.width
let barButton = UIBarButtonItem()
barButton.customView = button
self.navigationItem.rightBarButtonItems = [notificationButton, barButton]
And the result is,
In second solution it working but the image is redrawing like mirroring to down. Please help me how to place rounded profile picture in UIBarButtonItems.
I've used the following approch,
let button = UIButton(type: .system)
button.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
button.layer.cornerRadius = 15
button.clipsToBounds = true
button.imageView?.contentMode = .scaleAspectFit
let imageData = try? Data(contentsOf: URL(string : "https://www.w3schools.com/howto/img_avatar.png")!)
if let imageData = imageData , let image = UIImage(data: imageData)?.resizeImage(to: button.frame.size) {
button.setBackgroundImage(image, for: .normal)
}
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: button)
To resize the image
extension UIImage {
func resizeImage(to size: CGSize) -> UIImage {
return UIGraphicsImageRenderer(size: size).image { _ in
draw(in: CGRect(origin: .zero, size: size))
}
}}
In the above example, I've used Data(contentsOf: URL) to load image from the internet, but it is better to fetch the image asynchronously. Check this for more details.
Try this
let frame = CGRect(x: 0, y: 0, width: 30, height: 30)
let customView = UIView(frame: frame)
let imageView = UIImageView(image: UIImage(named: "turtle"))
imageView.frame = frame
imageView.layer.cornerRadius = imageView.frame.height * 0.5
imageView.layer.masksToBounds = true
customView.addSubview(imageView)
navigationItem.rightBarButtonItems = [
UIBarButtonItem(systemItem: .action), UIBarButtonItem(customView: customView)
]
Instead of UIImage(name:) use your UIImage(data:) constructor
You do not need a custom button or an image view. And do not use corner rounding. Just draw the target image into the desired size with clipping to a circle and use that as the bar button item’s image.
I'm calling a JSQMessageViewController and adding an image as the title but it's not centred due to the offset caused by the Back left-button.
Here's my code for adding the image:
let imageView = UIImageView()
imageView.frame.size.width = 40
imageView.frame.size.height = 40
imageView.contentMode = .scaleAspectFit
let image = UIImage(named: "avatar_example")
imageView.image = image
navigationItem.titleView = imageView
Thanks :)
Are you sure that the problem is in JSQMessageViewController? Maybe you just need to use standard sizes from title view (44*44) for alignment.
let imageView = UIImageView(image: UIImage(named: "avatar_example"))
imageView.contentMode = .scaleAspectFit
let titleView = UIView(frame: CGRect(x: 0, y: 0, width: 44, height: 44))
imageView.frame = titleView.bounds
titleView.addSubview(imageView)
self.navigationItem.titleView = titleView
You need to actually get the width and height of the UINavigationBar and center the image accordingly. Try this
guard let bar = navigationController.navigationBar else { return }
let bannerWidth = bar.frame.size.width
let bannerHeight = bar.frame.size.height
// centers image vertically & horizontally
let bannerX = bannerWidth / 2 - imageView.frame.width / 2
let bannerY = bannerHeight / 2 - imageView.frame.height / 2
imageView.frame = CGRect(x: bannerX, y: bannerY, width: bannerWidth, height: bannerHeight)
imageView.contentMode = .scaleAspectFit
navigationItem.titleView = logoImageView
I have a logo in Swift 3 with the below code, but when I add a Bar button Item to the left, it pushes the logo across. As below:
CODE:
let logo = UIImage(named: "logo") as UIImage?
let imageView = UIImageView(image:logo)
imageView.frame.size.width = 100;
imageView.frame.size.height = 22;
imageView.contentMode = UIViewContentMode.scaleAspectFit
self.navigationItem.titleView = imageView
How do i move the logo back into the centre??
You can set frame like this for titleView. Change x and y positions as per your requirement.
let imageView = UIImageView(image: UIImage(named: "test"))
imageView.contentMode = UIViewContentMode.scaleAspectFit
let titleView = UIView(frame: CGRect(x: 0, y: 0, width: 44, height: 44))
imageView.frame = titleView.bounds
titleView.addSubview(imageView)
self.navigationItem.titleView = titleView
I want to customize my app's look by using a logo image as the navigation bar's title, instead of plain text. When I use this code
let logo = UIImage(named: "logo.png")
self.navigationItem.titleView = logo;
I get the error "UIImage is not convertible to UIView". How can I do this correctly?
Put it inside an UIImageView
let logo = UIImage(named: "logo.png")
let imageView = UIImageView(image:logo)
self.navigationItem.titleView = imageView
I use this. It works in iOS 8
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let image = UIImage(named: "YOURIMAGE")
navigationItem.titleView = UIImageView(image: image)
}
And here is an example how you can do it with CGRect.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 38, height: 38))
imageView.contentMode = .ScaleAspectFit
let image = UIImage(named: "YOURIMAGE")
imageView.image = image
navigationItem.titleView = imageView
}
Hope this will help.
For swift 4 and you can adjust imageView size
let logoContainer = UIView(frame: CGRect(x: 0, y: 0, width: 270, height: 30))
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 270, height: 30))
imageView.contentMode = .scaleAspectFit
let image = UIImage(named: "your_image")
imageView.image = image
logoContainer.addSubview(imageView)
navigationItem.titleView = logoContainer
I tried #Jack's answer above, the logo did appear however the image occupied the whole Navigation Bar. I wanted it to fit.
Swift 4, Xcode 9.2
1.Assign value to navigation controller, UIImage. Adjust size by dividing frame and Image size.
func addNavBarImage() {
let navController = navigationController!
let image = UIImage(named: "logo-signIn6.png") //Your logo url here
let imageView = UIImageView(image: image)
let bannerWidth = navController.navigationBar.frame.size.width
let bannerHeight = navController.navigationBar.frame.size.height
let bannerX = bannerWidth / 2 - (image?.size.width)! / 2
let bannerY = bannerHeight / 2 - (image?.size.height)! / 2
imageView.frame = CGRect(x: bannerX, y: bannerY, width: bannerWidth, height: bannerHeight)
imageView.contentMode = .scaleAspectFit
navigationItem.titleView = imageView
}
Add the function right under viewDidLoad()
addNavBarImage()
Note on the image asset. Before uploading, I adjusted the logo with extra margins rather than cropped at the edges.
Final result:
You can use custom UINavigationItem so, you only need to change "Navigation Item" as YourCustomClass on the Main.storyboard.
In Swift 3
class FixedImageNavigationItem: UINavigationItem {
private let fixedImage : UIImage = UIImage(named: "your-header-logo.png")!
private let imageView : UIImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 50, height: 37.5))
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
imageView.contentMode = .scaleAspectFit
imageView.image = fixedImage
self.titleView = imageView
}
}
Here is a handy function for Swift 4.2, shows an image with title text:-
override func viewDidLoad() {
super.viewDidLoad()
//Sets the navigation title with text and image
self.navigationItem.titleView = navTitleWithImageAndText(titleText: "Dean Stanley", imageName: "online")
}
func navTitleWithImageAndText(titleText: String, imageName: String) -> UIView {
// Creates a new UIView
let titleView = UIView()
// Creates a new text label
let label = UILabel()
label.text = titleText
label.sizeToFit()
label.center = titleView.center
label.textAlignment = NSTextAlignment.center
// Creates the image view
let image = UIImageView()
image.image = UIImage(named: imageName)
// Maintains the image's aspect ratio:
let imageAspect = image.image!.size.width / image.image!.size.height
// Sets the image frame so that it's immediately before the text:
let imageX = label.frame.origin.x - label.frame.size.height * imageAspect
let imageY = label.frame.origin.y
let imageWidth = label.frame.size.height * imageAspect
let imageHeight = label.frame.size.height
image.frame = CGRect(x: imageX, y: imageY, width: imageWidth, height: imageHeight)
image.contentMode = UIView.ContentMode.scaleAspectFit
// Adds both the label and image view to the titleView
titleView.addSubview(label)
titleView.addSubview(image)
// Sets the titleView frame to fit within the UINavigation Title
titleView.sizeToFit()
return titleView
}
this worked for me in Sept 2015 - Hope this helps someone out there.
// 1
var nav = self.navigationController?.navigationBar
// 2 set the style
nav?.barStyle = UIBarStyle.Black
nav?.tintColor = UIColor.yellowColor()
// 3
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
imageView.contentMode = .ScaleAspectFit
// 4
let image = UIImage(named: "logo.png")
imageView.image = image
// 5
navigationItem.titleView = imageView
I have written this for iOS 10 & iOS 11 and it worked for me:
extension UINavigationBar {
func setupNavigationBar() {
let titleImageWidth = frame.size.width * 0.32
let titleImageHeight = frame.size.height * 0.64
var navigationBarIconimageView = UIImageView()
if #available(iOS 11.0, *) {
navigationBarIconimageView.widthAnchor.constraint(equalToConstant: titleImageWidth).isActive = true
navigationBarIconimageView.heightAnchor.constraint(equalToConstant: titleImageHeight).isActive = true
} else {
navigationBarIconimageView = UIImageView(frame: CGRect(x: 0, y: 0, width: titleImageWidth, height: titleImageHeight))
}
navigationBarIconimageView.contentMode = .scaleAspectFit
navigationBarIconimageView.image = UIImage(named: "image")
topItem?.titleView = navigationBarIconimageView
}
}
Swift 5.1+, Xcode 13+
Sometimes if your image is in high resolution then, imageView shifts from centre, I would suggest using this method
lazy var navigationTitleImageView = UIImageView()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationTitleImageView.image = logo
self.navigationTitleImageView.contentMode = .scaleAspectFit
self.navigationTitleImageView.translatesAutoresizingMaskIntoConstraints = false
if let navC = self.navigationController{
navC.navigationBar.addSubview(self.navigationTitleImageView)
self.navigationTitleImageView.centerXAnchor.constraint(equalTo: navC.navigationBar.centerXAnchor).isActive = true
self.navigationTitleImageView.centerYAnchor.constraint(equalTo: navC.navigationBar.centerYAnchor, constant: 0).isActive = true
self.navigationTitleImageView.widthAnchor.constraint(equalTo: navC.navigationBar.widthAnchor, multiplier: 0.2).isActive = true
self.navigationTitleImageView.heightAnchor.constraint(equalTo: navC.navigationBar.widthAnchor, multiplier: 0.088).isActive = true
}
}
and viewWillDisappear()
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.navigationTitleImageView.removeFromSuperview()
}
or else just reduce the image size
If you'd prefer to use autolayout, and want a permanent fixed image in the navigation bar, that doesn't animate in with each screen, this solution works well:
class CustomTitleNavigationController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
let logo = UIImage(named: "MyHeaderImage")
let imageView = UIImageView(image:logo)
imageView.contentMode = .scaleAspectFit
imageView.translatesAutoresizingMaskIntoConstraints = false
navigationBar.addSubview(imageView)
navigationBar.addConstraint (navigationBar.leftAnchor.constraint(equalTo: imageView.leftAnchor, constant: 0))
navigationBar.addConstraint (navigationBar.rightAnchor.constraint(equalTo: imageView.rightAnchor, constant: 0))
navigationBar.addConstraint (navigationBar.topAnchor.constraint(equalTo: imageView.topAnchor, constant: 0))
navigationBar.addConstraint (navigationBar.bottomAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 0))
}
Programmatically could be done like this.
private var imageView: UIView {
let bannerWidth = navigationBar.frame.size.width * 0.5 // 0.5 its multiplier to get correct image width
let bannerHeight = navigationBar.frame.size.height
let view = UIView()
view.backgroundColor = .clear
view.frame = CGRect(x: 0, y: 0, width: bannerWidth, height: bannerHeight)
let image = UIImage(named: "your_image_name")
let imageView = UIImageView(image: image)
imageView.contentMode = .scaleAspectFit
imageView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height)
view.addSubview(imageView)
return view
}
The just change titleView
navigationItem.titleView = imageView
let's do try and checkout
let image = UIImage(named: "Navbar_bg.png")
navigationItem.titleView = UIImageView(image: image)
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
imageView.contentMode = .ScaleAspectFit
let imageView = UIImageView(frame: (CGRect(x: 0, y: 0, width: 40, height:
40)))
imageView.contentMode = .scaleAspectFit
let image = UIImage (named: "logo") // logo is your NPG asset
imageView.image = image
self.navigationItem.titleView = imageView
Works for me in swift 4 (square image 40x40)
let imageView = UIImageView()
imageView.frame.size.width = 40
imageView.frame.size.height = 40
imageView.contentMode = .scaleAspectFit
let image = UIImage(named: "YOUR_IMAGE_NAME")
imageView.image = image
navigationItem.titleView = imageView
If you want other measures, try
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 50, height: 100.5)))
imageView.contentMode = .scaleAspectFit
let image = UIImage(named: "YOUR_IMAGE_NAME")
imageView.image = image
navigationItem.titleView = imageView
I hope it serves you. It works for me.
Objective-C version:
//create the space for the image
UIImageView *myImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 256, 144)];
//bind the image with the ImageView allocated
myImage.image = [UIImage imageNamed:#"logo.png"];
//add image into imageview
_myNavigationItem.titleView = myImage;
Just in case someone (like me) had arrived here looking for the answer in Objective-C.
This worked for me... try it
let image : UIImage = UIImage(named: "LogoName")
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 25, height: 25))
imageView.contentMode = .scaleAspectFit
imageView.image = image
navigationItem.titleView = imageView
In order to get the image view with the proper size and in the center, you should use the following approach:
let width = 120 // choose the image width
let height = 20 // choose the image height
let titleView = UIView(frame: CGRect(x: 0, y: 0, width: view.bounds.width, height: 44)) //44 is the standard size of the top bar
let imageView = UIImageView(frame: CGRect(x: (view.bounds.width - width)/2, y: (44 - height)/2, width: width, height: height))
imageView.contentMode = .scaleAspectFit //choose other if it makes sense
imageView.image = UIImage(named: "your_image_name")
titleView.addSubview(imageView)
navigationItem.titleView = titleView