How to get circle imageView in as titleView of navigation bar iOS

Viewed 121

I am trying to get a navigation bar similar to the one in iOS messages app. This is what I have, and it creates a bit of a circle shape but gets cut off. If you were to recreate the centered image from Messages how would you?

let imageView = UIImageView(image: UIImage(named: "test-image"))
imageView.contentMode = .scaleAspectFit

let titleView = UIView(frame: CGRect(x: 0, y: 0, width: 44, height: 44))
imageView.frame = titleView.bounds
imageView.layer.masksToBounds = true
imageView.layer.cornerRadius = imageView.frame.height / 2

titleView.addSubview(imageView)
    

self.navigationItem.titleView = titleView

The current outcome with this snippet:

enter image description here

The desired outcome:

enter image description here

Tested solutions In dark mode:

enter image description here

Please excuse my eggs ;) It's my favorite test pic

2 Answers

Set image view content mode .scaleAspectFill

imageView.contentMode = .scaleAspectFill

The following is what I have done.

I use two functions to work with an image. The makeCutout function creates a square cutout based on the height of an image of your selection. The position of the cutout is placed at the center of the source image. (See let cutoutRect = ...) The second one, the makeCircularImage function, makes the cutout image circular. Note that I'm assuming the original image is horizontally-long, which means that the diameter of the cutout will be the height of the image.

import UIKit

class ViewController: UIViewController {
    // MARK: - Life cycle
    override func viewDidLoad() {
        super.viewDidLoad()
        
        if let image = UIImage(named: "jenniferGarner.jpg") {
            let imageWidth = image.size.width
            let imageHeight = image.size.height
            let cutoutRect = CGRect(origin: CGPoint(x: (imageWidth - imageHeight) / 2.0, y: 0.0), size: CGSize(width: imageHeight, height: imageHeight))
            if let cutoutImage = makeCutout(image: image, rect: cutoutRect) {
                /* making it a circular image */
                if let circleImage = makeCircularImage(sourceImage: cutoutImage, diameter: cutoutImage.size.height) {
                    testImageView.isHidden = true
                    let imageView = UIImageView(image: circleImage)
                    imageView.contentMode = .scaleAspectFit
                    let titleView = UIView(frame: CGRect(x: 0, y: 0, width: 44, height: 44))
                    //titleView.backgroundColor = UIColor.green
                    imageView.frame = titleView.bounds
                    imageView.layer.masksToBounds = true
                    imageView.layer.cornerRadius = imageView.frame.height / 2
                    titleView.addSubview(imageView)
                    self.navigationItem.titleView = titleView
                }
            }
        }
    }
    
    
    // MARK: - Making a cutout image
    func makeCutout(image: UIImage, rect: CGRect) -> UIImage? {
        if let cgImage = image.cgImage {
            let contextImage: UIImage = UIImage(cgImage: cgImage)
            
            // Create bitmap image from context using the rect
            var croppedContextImage: CGImage? = nil
            if let contextImage = contextImage.cgImage {
                if let croppedImage = contextImage.cropping(to: rect) {
                    croppedContextImage = croppedImage
                }
            }
            
            // Create a new image based on the imageRef and rotate back to the original orientation
            if let croppedImage: CGImage = croppedContextImage {
                let image: UIImage = UIImage(cgImage: croppedImage, scale: image.scale, orientation: image.imageOrientation)
                return image
            }
        }
        return nil
    }
    
    func makeCircularImage(sourceImage: UIImage, diameter: CGFloat) -> UIImage? {
        let imageView = UIImageView(image: sourceImage)
        let layer = imageView.layer
        layer.masksToBounds = true
        layer.cornerRadius = diameter / 2.0
        UIGraphicsBeginImageContext(imageView.bounds.size)
        layer.render(in: UIGraphicsGetCurrentContext()!)
        if let finalImage = UIGraphicsGetImageFromCurrentImageContext() {
            UIGraphicsEndImageContext()
            return finalImage
        }
        return nil
    }
}

I have Jeniffer Garner as a guest as shown below. The source image size is 480 px X 180 px.

enter image description here

The following is the final work with an iPhone simulator with the dark mode.

enter image description here

Related