Change UIView Layer - Swift - ios

I try to implement UIView with sequence. With below code the output like in this picture. (This is normal behaviour)
But I want to line up like below picture
Elements sorted from right!
imageView.trailingAnchor.constraint(equalTo: participantView.safeAreaLayoutGuide.trailingAnchor, constant: CGFloat(-(counter * widthX - 5 * counter)) ).isActive = true
What can I do now?
let widthX = 30
var counter = 0
for x in element {
guard let image = x.image else { continue }
let urlX = URL(string: "...")
let imageView = UIImageView()
participantView.addSubview(imageView)
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.trailingAnchor.constraint(equalTo: participantView.safeAreaLayoutGuide.trailingAnchor, constant: CGFloat(-(counter * widthX - 5 * counter)) ).isActive = true
imageView.topAnchor.constraint(equalTo: participantView.topAnchor, constant: 0).isActive = true
imageView.bottomAnchor.constraint(equalTo: participantView.bottomAnchor, constant: 0).isActive = true
imageView.widthAnchor.constraint(equalToConstant: 30).isActive = true
imageView.backgroundColor = .white
imageView.layer.cornerRadius = 15
imageView.clipsToBounds = true
imageView.contentMode = .scaleAspectFit
imageView.layer.borderWidth = 1
imageView.layer.borderColor = UIColor.lightGray.cgColor
counter += 1
imageView.kf.setImage(with: urlX)
}

Replace
participantView.addSubview(imageView)
with
participantView.insertSubview(imageView,at:0)
position of 1 ,2 ..etc (left/right alignment) depends on image

Related

Swift Autolayout - Height Anchor not being applied

I am working on a "Profile View Controller" which is inside a TableViewCell and table cell dimension is set as UITableView.automaticDimension:
The problem is that I would like to set the background image view (Blue) with a variable height based on cell width and a 16:9 ratio. For some reason I am not being able to change the view height even if I set the constant.
Here the code:
let topView : UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.layer.cornerRadius = 20
view.backgroundColor = .yoofitDarkBlue
view.layer.masksToBounds = true
view.layer.shadowColor = UIColor.lightGray.cgColor
view.layer.borderWidth = 0.5
view.layer.borderColor = UIColor.yoofitDarkBlue.cgColor
view.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
view.layer.shadowRadius = 12.0
view.layer.shadowOpacity = 0.7
return view
}()
let userImage : UIImageView = {
let i = UIImageView()
i.translatesAutoresizingMaskIntoConstraints = false
i.image = UIImage(named: "user2")
i.layer.masksToBounds = true
i.layer.cornerRadius = 75
i.layer.borderWidth = 1
i.layer.borderColor = UIColor.white.cgColor
return i
}()
var userNameLabel:UILabel = {
let l = UILabel()
l.translatesAutoresizingMaskIntoConstraints = false
l.font = UIFont(name: "AvenirNext-DemiBold", size: 20)
l.textAlignment = .center
l.textColor = .yoofitBlack
return l
}()
func setupViews() {
self.backgroundColor = .clear
self.selectionStyle = .none
addSubview(topView)
let width = self.frame.width
print(width) // print 320
topView.topAnchor.constraint(equalTo: topAnchor, constant: 10).isActive = true
topView.leftAnchor.constraint(equalTo: leftAnchor, constant: 8).isActive = true
topView.rightAnchor.constraint(equalTo: rightAnchor, constant: -8).isActive = true
topView.heightAnchor.constraint(equalToConstant: width/16*9).isActive = true // this doesn't work even if I set another number like 600
topView.layoutIfNeeded()
addSubview(userImage)
userImage.centerYAnchor.constraint(equalTo: topView.bottomAnchor).isActive = true
userImage.centerXAnchor.constraint(equalTo: topView.centerXAnchor).isActive = true
userImage.widthAnchor.constraint(equalToConstant: 150).isActive = true
userImage.heightAnchor.constraint(equalToConstant: 150).isActive = true
addSubview(userNameLabel)
userNameLabel.topAnchor.constraint(equalTo: userImage.bottomAnchor, constant: 10).isActive = true
userNameLabel.centerXAnchor.constraint(equalTo: userImage.centerXAnchor).isActive = true
userNameLabel.widthAnchor.constraint(equalToConstant: 200).isActive = true
userNameLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true
userNameLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -20).isActive = true
}
PLEASE NOTE THERE ARE 2 answers to this question. The latter is definitely the correct one but the first maybe may help others.
So this is how I fixed it but I hope to get better answers. This answer helped me to go to the right path (iOS: How to Align The Center of a View With The Bottom of Another View With AutoLayout)
I have added a containing view which is twice as the required size of my top view (the blue one).
I centered the picture on the containing view.
self.conteiningView.backgroundColor = .red // I made this red so you can visually see how the views are related to each other
let width = self.frame.width
self.addSubview(conteiningView)
conteiningView.topAnchor.constraint(equalTo: topAnchor, constant: 8).isActive = true
conteiningView.leftAnchor.constraint(equalTo: leftAnchor, constant: 8).isActive = true
conteiningView.rightAnchor.constraint(equalTo: rightAnchor, constant: -8).isActive = true
conteiningView.heightAnchor.constraint(equalToConstant: (width/16*9)*2).isActive = true // twice of the blue view
conteiningView.layoutIfNeeded()
self.conteiningView.addSubview(topView)
topView.topAnchor.constraint(equalTo: conteiningView.topAnchor).isActive = true
topView.leftAnchor.constraint(equalTo: conteiningView.leftAnchor).isActive = true
topView.rightAnchor.constraint(equalTo: conteiningView.rightAnchor).isActive = true
topView.heightAnchor.constraint(equalToConstant: width/16*9).isActive = true // 16:9 ration
conteiningView.addSubview(userImage)
userImage.centerYAnchor.constraint(equalTo: conteiningView.centerYAnchor).isActive = true
userImage.centerXAnchor.constraint(equalTo: conteiningView.centerXAnchor).isActive = true
userImage.widthAnchor.constraint(equalToConstant: width/2).isActive = true
userImage.heightAnchor.constraint(equalToConstant: width/2).isActive = true
userImage.layer.cornerRadius = width/4 // to mantain nice proportions
conteiningView.addSubview(userNameLabel)
userNameLabel.topAnchor.constraint(equalTo: userImage.bottomAnchor, constant: 10).isActive = true
userNameLabel.centerXAnchor.constraint(equalTo: userImage.centerXAnchor).isActive = true
userNameLabel.widthAnchor.constraint(equalToConstant: 200).isActive = true
userNameLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true
With red background:
With clear background:
UPDATE: The answer above works but I have actually found the problem:
Even if I had set:
self.tableView.rowHeight = UITableView.automaticDimension
self.tableView.estimatedRowHeight = 300
For some (silly me) I had also implemented:
tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
This, of course, does not be implemented for the automatic dimension to work.
removing that allowed to use the following code to achieve the same result but without setting a predefined height:
self.addSubview(conteiningView)
conteiningView.topAnchor.constraint(equalTo: topAnchor, constant: 8).isActive = true
conteiningView.leftAnchor.constraint(equalTo: leftAnchor, constant: 8).isActive = true
conteiningView.rightAnchor.constraint(equalTo: rightAnchor, constant: -8).isActive = true
conteiningView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
conteiningView.layoutIfNeeded()
self.conteiningView.addSubview(topView)
topView.topAnchor.constraint(equalTo: conteiningView.topAnchor).isActive = true
topView.leftAnchor.constraint(equalTo: conteiningView.leftAnchor).isActive = true
topView.rightAnchor.constraint(equalTo: conteiningView.rightAnchor).isActive = true
topView.heightAnchor.constraint(equalToConstant: width/16*9).isActive = true
conteiningView.addSubview(userImage)
userImage.centerYAnchor.constraint(equalTo: topView.bottomAnchor).isActive = true // the vertical center is now set nicely at bottom edge of my top view.
userImage.centerXAnchor.constraint(equalTo: topView.centerXAnchor).isActive = true
userImage.widthAnchor.constraint(equalToConstant: width/2).isActive = true
userImage.heightAnchor.constraint(equalToConstant: width/2).isActive = true
userImage.layer.cornerRadius = width/4
conteiningView.addSubview(userNameLabel)
userNameLabel.topAnchor.constraint(equalTo: userImage.bottomAnchor, constant: 2).isActive = true
userNameLabel.centerXAnchor.constraint(equalTo: userImage.centerXAnchor).isActive = true
userNameLabel.widthAnchor.constraint(equalToConstant: 200).isActive = true
userNameLabel.heightAnchor.constraint(equalToConstant: 35).isActive = true

Swift - Duplicate UIView

I'm currently trying to achieve a Shimmer effect in Swift. To do that I create a gray UIView, and another on top of it with an effect.
The problem is that I'm writing the same code twice...
let profileShimmerView = UIView()
profileShimmerView.backgroundColor = whiteClear
profileShimmerView.layer.cornerRadius = 20
profileShimmerView.clipsToBounds = true
let profileView = UIView()
profileView.backgroundColor = grayClear
profileView.layer.cornerRadius = 20
profileView.clipsToBounds = true
self.addSubview(profileView)
self.addSubview(profileShimmerView)
profileShimmerView.translatesAutoresizingMaskIntoConstraints = false
profileShimmerView.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 45).isActive = true
profileShimmerView.topAnchor.constraint(equalTo: self.topAnchor, constant: 15).isActive = true
profileShimmerView.widthAnchor.constraint(equalToConstant: 40).isActive = true
profileShimmerView.heightAnchor.constraint(equalToConstant: 40).isActive = true
profileView.translatesAutoresizingMaskIntoConstraints = false
profileView.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 45).isActive = true
profileView.topAnchor.constraint(equalTo: self.topAnchor, constant: 15).isActive = true
profileView.widthAnchor.constraint(equalToConstant: 40).isActive = true
profileView.heightAnchor.constraint(equalToConstant: 40).isActive = true
Is there a more simple way to achieve that?
You can create a function
func shared(color : UIColor)->UIView {
let v = UIView()
v.backgroundColor = color
v.layer.cornerRadius = 20
v.clipsToBounds = true
self.addSubview(v)
v.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
v.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 45),
v.topAnchor.constraint(equalTo: self.topAnchor, constant: 15),
v.widthAnchor.constraint(equalToConstant: 40),
v.heightAnchor.constraint(equalToConstant: 40)
])
return v
}

ios UIImage going outside of UIImageView Border

Here black border shows the Parent UIView of UIImageView and Red border showing UIImageView i'm downloading image from server but the image is going outside of the UIImageView area as shown in the image. I'm doing it programmatically any help would be very much appreciated. I'm adding code block below
let bottomView : UIView = UIView(frame: CGRect(x : 10, y: stackView.height, width: view.width * 0.75, height: view.width * 0.75 ))
view.addSubview(bottomView)
bottomView.layer.borderColor = UIColor.black.cgColor
bottomView.layer.borderWidth = 1
bottomView.translatesAutoresizingMaskIntoConstraints = false
bottomView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
bottomView.topAnchor.constraint(equalTo: stackView.bottomAnchor, constant: -20).isActive = true
bottomView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10).isActive = true
bottomView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10).isActive = true
bottomView.widthAnchor.constraint(equalToConstant: view.width * 0.75).isActive = true
bottomView.heightAnchor.constraint(equalToConstant: view.width * 0.75).isActive = true
let imageView : UIImageView = UIImageView(frame : CGRect(x: 0, y: 0, width: 250, height: 250 ))
imageView.layer.borderColor = UIColor.red.cgColor
imageView.layer.borderWidth = 1
bottomView.addSubview(imageView)
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.centerXAnchor.constraint(equalTo: bottomView.centerXAnchor).isActive = true
imageView.centerYAnchor.constraint(equalTo: bottomView.centerYAnchor).isActive = true
imageView.widthAnchor.constraint(equalToConstant: 250).isActive = true
imageView.heightAnchor.constraint(equalToConstant: 250).isActive = true
imageView.downloadedFrom(link: (sizeResult?.results![0].data?.size_Chart?.mobile_image?.imageValue?.imageMain?.url)!, contentMode : .scaleAspectFill)
this bottomView will be added UIAlertViewController.
This image shows ** contentMode is Aspect Fit **
You can use clip to bound with your image view, Definitely It will resolve your issue.
Swift:
override func viewDidLoad() {
super.viewDidLoad()
self.bottomView.clipsToBounds = false
self.imageView.clipsToBounds = true
}
Set the properties of uiimageview and content mode:
self.imageView.clipsToBounds = true
self.imageView.contentMode = .scaleAspectFit
imageView?.contentMode = .scaleAspectFit
self.imageView.clipsToBounds = true
it was worked for me..
The last line of your code should be this -
imageView.downloadedFrom(link: (sizeResult?.results![0].data?.size_Chart?.mobile_image?.imageValue?.imageMain?.url)!, contentMode : .scaleAspectFit)

Swift 4: Add View on top of all controllers

Conditions:
Swift 4, Xcode 9.3
Target: iOS 11.3
UI Done Programatically
Using Constraints
My Root View Controller is a Navigation
Situation:
I wanted to float an audio player that will be visible throughout the app.
I did an AudioPlayer.swift class that contains the user interface of the audio player.
AudioPlayer.swift
import Foundation
import UIKit
import FRadioPlayer
class AudioPlayer: UIView {
let screenSize: CGRect = UIScreen.main.bounds
let playerImage: UIImageView = {
let iv = UIImageView()
iv.translatesAutoresizingMaskIntoConstraints = false
iv.contentMode = .scaleAspectFill
iv.layer.masksToBounds = true
return iv
}()
let playerTitle: UILabel = {
let l = UILabel()
l.textColor = .darkGray
l.font = UIFont.boldSystemFont(ofSize: 13)
l.translatesAutoresizingMaskIntoConstraints = false
return l
}()
let playerSeriesTitle: UILabel = {
let l = UILabel()
l.textColor = .darkGray
l.font = UIFont.boldSystemFont(ofSize: 12)
l.translatesAutoresizingMaskIntoConstraints = false
return l
}()
override init(frame: CGRect) {
super.init(frame: frame)
translatesAutoresizingMaskIntoConstraints = false
setupAudioControls()
}
private func setupAudioControls(){
let appDelegate = AppDelegate.sharedInstance
self.backgroundColor = UIColor.init(hex: "#EBE4D3")
self.addSubview(playerImage)
self.addSubview(playerTitle)
self.addSubview(playerSeriesTitle)
self.heightAnchor.constraint(equalToConstant: 150).isActive = true
self.bottomAnchor.constraint(equalTo: appDelegate().rootView ).isActive = true
self.leadingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.leadingAnchor).isActive = true
self.trailingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.trailingAnchor).isActive = true
playerImage.topAnchor.constraint(equalTo: self.topAnchor, constant: 10).isActive = true
playerImage.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 10).isActive = true
playerImage.widthAnchor.constraint(equalToConstant: 55).isActive = true
playerImage.heightAnchor.constraint(equalToConstant: 55).isActive = true
playerTitle.topAnchor.constraint(equalTo: self.topAnchor, constant: 5).isActive = true
playerTitle.leadingAnchor.constraint(equalTo: playerImage.trailingAnchor, constant: 10).isActive = true
playerTitle.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 10).isActive = true
playerTitle.heightAnchor.constraint(equalToConstant: 25).isActive = true
playerSeriesTitle.topAnchor.constraint(equalTo: playerTitle.topAnchor, constant: 20).isActive = true
playerSeriesTitle.leadingAnchor.constraint(equalTo: playerImage.trailingAnchor, constant: 10).isActive = true
playerSeriesTitle.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 10).isActive = true
playerSeriesTitle.heightAnchor.constraint(equalToConstant: 20).isActive = true
UIView.animate(withDuration: 0.5, animations: {
self.frame.origin.y -= 150
self.playerImage.frame.origin.y -= 150
self.playerTitle.frame.origin.y -= 150
self.playerSeriesTitle.frame.origin.y -= 150
}, completion: nil)
self.setNeedsLayout()
self.reloadInputViews()
}
}
Problem:
How can I add this to the Root View Controller to stay on top in all view controllers that I have in my app? Wherever I navigate, the player must stay on the bottom part of every controller. As you can see, I need a reference to the rootviewcontroller to set the contraints for the AudioPlayer but I failed in so many attempts (like calling the rootviewcontroller using AppDelegate)
I update it for you
add singleton static let shared = AudioPlayer()
add public func showAudioPlayer () --> to display Audio player
add as subview to UIApplication.shared.keyWindow?
TODO- add HideAudioPlayer()
Use like this
AudioPlayer.shared.showAudioPlayer()
Here is updated code
import Foundation
import UIKit
class AudioPlayer: UIView {
static let shared = AudioPlayer()
let screenSize: CGRect = UIScreen.main.bounds
let playerImage: UIImageView = {
let iv = UIImageView()
iv.translatesAutoresizingMaskIntoConstraints = false
iv.contentMode = .scaleAspectFill
iv.layer.masksToBounds = true
return iv
}()
let playerTitle: UILabel = {
let l = UILabel()
l.textColor = .darkGray
l.font = UIFont.boldSystemFont(ofSize: 13)
l.translatesAutoresizingMaskIntoConstraints = false
return l
}()
let playerSeriesTitle: UILabel = {
let l = UILabel()
l.textColor = .darkGray
l.font = UIFont.boldSystemFont(ofSize: 12)
l.translatesAutoresizingMaskIntoConstraints = false
return l
}()
override init(frame: CGRect) {
super.init(frame: frame)
translatesAutoresizingMaskIntoConstraints = false
// setupAudioControls()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public func showAudioPlayer (){
self.setupAudioControls()
}
private func setupAudioControls(){
self.backgroundColor = .red
self.addSubview(playerImage)
self.addSubview(playerTitle)
self.addSubview(playerSeriesTitle)
UIApplication.shared.keyWindow?.addSubview(self)
if let layoutGuide = UIApplication.shared.keyWindow?.layoutMarginsGuide {
self.heightAnchor.constraint(equalToConstant: 150).isActive = true
self.bottomAnchor.constraint(equalTo: layoutGuide.bottomAnchor ).isActive = true
self.leadingAnchor.constraint(equalTo: layoutGuide.leadingAnchor).isActive = true
self.trailingAnchor.constraint(equalTo: layoutGuide.trailingAnchor).isActive = true
}
playerImage.topAnchor.constraint(equalTo: self.topAnchor, constant: 10).isActive = true
playerImage.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 10).isActive = true
playerImage.widthAnchor.constraint(equalToConstant: 55).isActive = true
playerImage.heightAnchor.constraint(equalToConstant: 55).isActive = true
playerTitle.topAnchor.constraint(equalTo: self.topAnchor, constant: 5).isActive = true
playerTitle.leadingAnchor.constraint(equalTo: playerImage.trailingAnchor, constant: 10).isActive = true
playerTitle.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 10).isActive = true
playerTitle.heightAnchor.constraint(equalToConstant: 25).isActive = true
playerSeriesTitle.topAnchor.constraint(equalTo: playerTitle.topAnchor, constant: 20).isActive = true
playerSeriesTitle.leadingAnchor.constraint(equalTo: playerImage.trailingAnchor, constant: 10).isActive = true
playerSeriesTitle.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 10).isActive = true
playerSeriesTitle.heightAnchor.constraint(equalToConstant: 20).isActive = true
UIView.animate(withDuration: 0.5, animations: {
self.frame.origin.y -= 150
self.playerImage.frame.origin.y -= 150
self.playerTitle.frame.origin.y -= 150
self.playerSeriesTitle.frame.origin.y -= 150
}, completion: nil)
self.setNeedsLayout()
self.reloadInputViews()
}
}
If you want to show view in each view controller then as per view hierarchy you must have to add in UIWindow. UIWindow is base of all screen.
AppDelegate.shared.window?.addSubview(AudioPlayer)
You can add your view to UIWindow.
I am doing the same thing with below method in AppDelegate.
var window: UIWindow?
func addPlayerViewAtBottom() {
var bottomView : PlayerBottomView!
bottomView = PlayerBottomView(frame: CGRect(x: 0, y: UIScreen.main.bounds.size.height - 60, width: UIScreen.main.bounds.width, height: 60))
self.window?.addSubview(bottomView)
self.window?.bringSubview(toFront: bottomView)
}

titleview dissapears when a subview is added?

This is new to me so forgive me if I'm not asking the right question.
I'm following a tutorial where we are creating a few subviews inside of a titleview for the navigation bar so that a picture and username displays. When I create the intial titleview with a red background, it shows up as expected. However, when I add a container subview to place the text and image, the red titleview disappears. I finished the tutorial and the text shows up in the right place, but it doesn't allow me to add a tap gesture, since the titleview isn't there anymore to tap?
I'll add my code for this function- hopefully there's a stupid mistake that I'm missing.
func setupNavBarWithUser(user: User) {
let titleView = UIView()
titleView.frame = CGRect(x: 0, y: 0, width: 130, height: 35)
titleView.backgroundColor = UIColor.red
let containerView = UIView()
containerView.translatesAutoresizingMaskIntoConstraints = false
containerView.backgroundColor = UIColor.blue
titleView.addSubview(containerView)
let profileImageView = UIImageView()
profileImageView.translatesAutoresizingMaskIntoConstraints = false
profileImageView.contentMode = .scaleAspectFill
profileImageView.layer.cornerRadius = 20
profileImageView.clipsToBounds = true
if let profileImageUrl = user.profileImageUrl {
profileImageView.loadImageUsingCacheWithUrlString(urlString: profileImageUrl)
}
containerView.addSubview(profileImageView)
profileImageView.leftAnchor.constraint(equalTo: containerView.leftAnchor).isActive = true
profileImageView.centerYAnchor.constraint(equalTo: containerView.centerYAnchor).isActive = true
profileImageView.widthAnchor.constraint(equalToConstant: 35).isActive = true
profileImageView.heightAnchor.constraint(equalToConstant: 35).isActive = true
let nameLabel = UILabel()
containerView.addSubview(nameLabel)
nameLabel.text = user.name
nameLabel.translatesAutoresizingMaskIntoConstraints = false
nameLabel.leftAnchor.constraint(equalTo: profileImageView.rightAnchor, constant: 8).isActive = true
nameLabel.centerYAnchor.constraint(equalTo: containerView.centerYAnchor).isActive = true
nameLabel.rightAnchor.constraint(equalTo: containerView.rightAnchor).isActive = true
nameLabel.heightAnchor.constraint(equalToConstant: 40).isActive = true
containerView.centerXAnchor.constraint(equalTo: titleView.centerXAnchor).isActive = true
containerView.centerYAnchor.constraint(equalTo: titleView.centerYAnchor).isActive = true
self.navigationItem.titleView = titleView
titleView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(showChatController)))
titleView.isUserInteractionEnabled = true
}
Replace setupNavBarWithUser method with this:
func setupNavBarWithUser(user: User) {
let titleView = UIView()
titleView.frame = CGRect(x: 0, y: 0, width: 130, height: 45)
titleView.backgroundColor = UIColor.red
let containerView = UIView()
containerView.translatesAutoresizingMaskIntoConstraints = false
containerView.backgroundColor = UIColor.blue
self.navigationItem.titleView = titleView
titleView.addSubview(containerView)
containerView.topAnchor.constraint(equalTo: titleView.topAnchor, constant: 0).isActive = true
containerView.bottomAnchor.constraint(equalTo: titleView.bottomAnchor, constant: 0).isActive = true
containerView.leadingAnchor.constraint(equalTo: titleView.leadingAnchor, constant: 0).isActive = true
containerView.trailingAnchor.constraint(equalTo: titleView.trailingAnchor, constant: 0).isActive = true
let profileImageView = UIImageView()
profileImageView.translatesAutoresizingMaskIntoConstraints = false
profileImageView.contentMode = .scaleAspectFill
profileImageView.layer.cornerRadius = 20
profileImageView.clipsToBounds = true
if let profileImageUrl = user.profileImageUrl {
profileImageView.loadImageUsingCacheWithUrlString(urlString: profileImageUrl)
}
containerView.addSubview(profileImageView)
profileImageView.leftAnchor.constraint(equalTo: containerView.leftAnchor).isActive = true
profileImageView.centerYAnchor.constraint(equalTo: containerView.centerYAnchor).isActive = true
profileImageView.widthAnchor.constraint(equalToConstant: 35).isActive = true
profileImageView.heightAnchor.constraint(equalToConstant: 35).isActive = true
let nameLabel = UILabel()
containerView.addSubview(nameLabel)
nameLabel.text = user.name
nameLabel.translatesAutoresizingMaskIntoConstraints = false
nameLabel.leftAnchor.constraint(equalTo: profileImageView.rightAnchor, constant: 8).isActive = true
nameLabel.centerYAnchor.constraint(equalTo: containerView.centerYAnchor).isActive = true
nameLabel.rightAnchor.constraint(equalTo: containerView.rightAnchor).isActive = true
nameLabel.heightAnchor.constraint(equalToConstant: 40).isActive = true
self.navigationItem.titleView = titleView
titleView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(showChatController)))
titleView.isUserInteractionEnabled = true
}
You can compare the codes. As you can see you have to add subview in a proper order to set your constraints.

Resources