iOS auto_resizing code for each layouts - ios

Hi I am working on creating a view with code below.
I would like to make this code to auto layout to each iPhone sizes.
Which code should I add more?
There exist four emoticons in this code in the view, so I want to make each of them resizing itself regardless of iPhone layout such as iPhone 8, SE, 8+ and so on.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
let firstView:UIImageView = {
let imageView = UIImageView()
imageView.image = #imageLiteral(resourceName: "angry").withRenderingMode(.alwaysOriginal)
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
let secondView:UIImageView = {
let imageView = UIImageView()
imageView.image = #imageLiteral(resourceName: "crying").withRenderingMode(.alwaysOriginal)
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
let thirdView:UIImageView = {
let imageView = UIImageView()
imageView.image = #imageLiteral(resourceName: "heartEmpty").withRenderingMode(.alwaysOriginal)
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
let fourthView:UIImageView = {
let imageView = UIImageView()
imageView.image = #imageLiteral(resourceName: "joy").withRenderingMode(.alwaysOriginal)
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
func setupViews() {
view.addSubview(firstView)
// setup first view
firstView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
firstView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
firstView.widthAnchor.constraint(equalToConstant: 80).isActive = true
firstView.heightAnchor.constraint(equalToConstant: 80).isActive = true
view.addSubview(secondView)
// setup second view
secondView.leftAnchor.constraint(equalTo: firstView.rightAnchor, constant: 20).isActive = true
secondView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
secondView.widthAnchor.constraint(equalToConstant: 80).isActive = true
secondView.heightAnchor.constraint(equalToConstant: 80).isActive = true
view.addSubview(thirdView)
thirdView.leftAnchor.constraint(equalTo: secondView.rightAnchor, constant: 20).isActive = true
thirdView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
thirdView.widthAnchor.constraint(equalToConstant: 80).isActive = true
thirdView.heightAnchor.constraint(equalToConstant: 80).isActive = true
view.addSubview(fourthView)
fourthView.leftAnchor.constraint(equalTo: thirdView.rightAnchor, constant: 20).isActive = true
fourthView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
fourthView.widthAnchor.constraint(equalToConstant: 80).isActive = true
fourthView.heightAnchor.constraint(equalToConstant: 80).isActive = true
}
}

It's better to insert them all in a horizontal UIStackView with fill-Equally, by this items will resize according to the current size of the stackview

Related

How to add UIView Gesture - Programmatically UIView

I have searched a lot about adding a gesture on UIView when it is tapped. There are many solutions but none of them worked for me.
I have made UIView class programmatically and using the view in different classes.
Here is my class of UIView:
class PaymentServiceView: UIView {
private let views: UIView = {
let view = UIView()
view.backgroundColor = .white
// view.layer.maskedCorners = [.layerMinXMinYCorner,.layerMaxXMinYCorner]
view.layer.borderColor = UIColor.gray.cgColor
view.layer.shadowOpacity = 0.3
view.layer.shadowColor = UIColor.gray.cgColor
view.layer.shadowRadius = 10
view.layer.borderWidth = 0.1
view.layer.cornerRadius = 20
view.isUserInteractionEnabled = true
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private let titleLbl: UILabel = {
var label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.textAlignment = .center
label.textColor = UIColor.black
label.font = UIFont(name: AppFontName.circularStdRegular, size: 18)
label.clipsToBounds = true
return label
}()
private let subLbl: UILabel = {
var label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.textAlignment = .center
label.textColor = UIColor.gray
label.numberOfLines = 0
label.textAlignment = .left
label.font = UIFont(name: AppFontName.robotoRegular, size: 15)
label.clipsToBounds = true
return label
}()
private let image: UIImageView = {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFit
imageView.clipsToBounds = true
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
private let btnImage: UIImageView = {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFit
imageView.clipsToBounds = true
imageView.image = UIImage(named: IconName.chevron_down)?.transform(withNewColor: UIColor.btnGray)
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
init(titleLabel: String, subTitleLabel: String, imageName: String) {
super.init(frame: CGRect.zero)
self.addSubview(views)
self.views.addSubview(btnImage)
self.views.addSubview(titleLbl)
self.views.addSubview(image)
self.views.addSubview(subLbl)
titleLbl.text = titleLabel
image.image = UIImage(named: imageName)
subLbl.text = subTitleLabel
setupConstraints()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupConstraints() {
self.views.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
self.views.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
self.views.heightAnchor.constraint(equalToConstant: 150).isActive = true
self.views.widthAnchor.constraint(equalToConstant: 320).isActive = true
self.image.centerYAnchor.constraint(equalTo: self.views.centerYAnchor).isActive = true
self.image.leadingAnchor.constraint(equalTo: self.views.leadingAnchor, constant: 15).isActive = true
self.image.widthAnchor.constraint(equalToConstant: 30).isActive = true
self.image.heightAnchor.constraint(equalToConstant: 30).isActive = true
self.titleLbl.centerYAnchor.constraint(equalTo: self.views.centerYAnchor, constant: -35).isActive = true
self.titleLbl.leadingAnchor.constraint(equalTo: image.trailingAnchor, constant: 15).isActive = true
self.subLbl.topAnchor.constraint(equalTo: titleLbl.bottomAnchor, constant: 5).isActive = true
self.subLbl.leadingAnchor.constraint(equalTo: image.trailingAnchor, constant: 15).isActive = true
self.subLbl.trailingAnchor.constraint(equalTo: btnImage.leadingAnchor, constant: -15).isActive = true
btnImage.topAnchor.constraint(equalTo: views.topAnchor, constant: 55).isActive = true
btnImage.rightAnchor.constraint(equalTo: views.rightAnchor, constant: -10).isActive = true
btnImage.heightAnchor.constraint(equalToConstant: 10).isActive = true
}
}
Now Im using this UIView class in PaymentServicesViewController
class PaymentServicesViewController: UIViewController {
private (set) lazy var headerView: HeaderView = { [unowned self] in
let view = HeaderView.init(titleLbl: Headings.paymentService, closeAction: {
self.navigationController?.popViewController(animated: true)
}, nextAction: {
print("next")
}, previousAction: {
self.navigationController?.popViewController(animated: true)
})
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private let fundTransferView: PaymentServiceView = {
let view = PaymentServiceView(titleLabel: Headings.fundTransfer, subTitleLabel: Description.fundTransferDecription , imageName: IconName.fundImage )
view.isUserInteractionEnabled = true
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private let subscriptionView: PaymentServiceView = {
let view = PaymentServiceView(titleLabel: Headings.subscribe, subTitleLabel: Description.subscriptionDescription, imageName: IconName.subImage )
view.isUserInteractionEnabled = true
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private let billPaymentView: PaymentServiceView = {
let view = PaymentServiceView(titleLabel: Headings.billPayment, subTitleLabel: Description.billPaymentDescription , imageName: IconName.billImage )
view.isUserInteractionEnabled = true
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .gray2
let fundtrasnferGesture = UITapGestureRecognizer(target: self, action: #selector(fundTranferTapped))
fundTransferView.isUserInteractionEnabled = true
self.fundTransferView.addGestureRecognizer(fundtrasnferGesture)
let subscribeGesture = UITapGestureRecognizer(target: self, action: #selector(subscribeTapped))
subscriptionView.isUserInteractionEnabled = true
self.subscriptionView.addGestureRecognizer(subscribeGesture)
let billPaymentGesture = UITapGestureRecognizer(target: self, action: #selector(billPaymentTapped))
fundTransferView.isUserInteractionEnabled = true
self.billPaymentView.addGestureRecognizer(billPaymentGesture)
view.addSubview(headerView)
view.addSubview(subscriptionView)
view.addSubview(fundTransferView)
view.addSubview(billPaymentView)
setupConstraint()
}
#objc func fundTranferTapped(sender: UITapGestureRecognizer) {
print("FundTransfer Tapped.")
}
#objc func subscribeTapped(sender: UITapGestureRecognizer) {
print("Subscribe Tapped.")
}
#objc func billPaymentTapped(sender: UITapGestureRecognizer) {
print("BillPayment Tapped.")
}
private func setupConstraint() {
headerView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
headerView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
headerView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
headerView.heightAnchor.constraint(equalToConstant: 100).isActive = true
subscriptionView.trailingAnchor.constraint(equalTo: fundTransferView.trailingAnchor, constant: 0).isActive = true
subscriptionView.leadingAnchor.constraint(equalTo: fundTransferView.leadingAnchor, constant: 0).isActive = true
subscriptionView.bottomAnchor.constraint(equalTo: fundTransferView.topAnchor, constant: -130).isActive = true
fundTransferView.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0).isActive = true
fundTransferView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 0).isActive = true
billPaymentView.leadingAnchor.constraint(equalTo: fundTransferView.leadingAnchor, constant: 0).isActive = true
billPaymentView.trailingAnchor.constraint(equalTo: fundTransferView.trailingAnchor).isActive = true
billPaymentView.topAnchor.constraint(equalTo: fundTransferView.bottomAnchor, constant: 130).isActive = true
}
}
I know there is a small mistake I'm doing but not sure. Help would be appreciated, Thank you.
You are missing a couple constraints...
If you add this at the end of viewDidLoad():
subscriptionView.clipsToBounds = true
fundTransferView.clipsToBounds = true
billPaymentView.clipsToBounds = true
You'll see that the views "disappear":
because they have no Width or Height constraints (so their size is .zero).
In setupConstraints() in your PaymentServiceView class, add these two lines:
self.widthAnchor.constraint(equalTo: self.views.widthAnchor).isActive = true
self.heightAnchor.constraint(equalTo: self.views.heightAnchor).isActive = true
Now, the PaymentServiceView will be the same Width and Height as self.views view.
However, now that the views have Heights:
your layout needs to be adjusted.
Change the .clipsToBounds back to false (remove those added lines) so the shadows won't be clipped, and change these constraints in your controller (adjust the 15 and -15 to your liking):
//subscriptionView.bottomAnchor.constraint(equalTo: fundTransferView.topAnchor, constant: -130).isActive = true
subscriptionView.bottomAnchor.constraint(equalTo: fundTransferView.topAnchor, constant: 15).isActive = true
//billPaymentView.topAnchor.constraint(equalTo: fundTransferView.bottomAnchor, constant: 130).isActive = true
billPaymentView.topAnchor.constraint(equalTo: fundTransferView.bottomAnchor, constant: -15).isActive = true
and we get:
Now, because the views have a size, the Tap Gestures will work.

displaying images in a stack view

Is it possible to display an image from the assets folder to a uistackview programmatically? If so, how would you go about doing it?
I already know how to create a stack view filled with labels.
fileprivate lazy var stack: UIStackView = {
let stack = UIStackView(arrangedSubviews: [goalCompleteLabel, completeMoreGoalsLabel])
stack.translatesAutoresizingMaskIntoConstraints = false
stack.axis = .vertical
return stack
} ()
First set your image in imageView (set in it its constraints for more control of image dimension) and your label under your class controller:
let image: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(named: "yourImage")?.withRenderingMode(.alwaysOriginal)
imageView.backgroundColor = .gray
imageView.layer.cornerRadius = 8
imageView.clipsToBounds = true
imageView.contentMode = .scaleAspectFill
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.heightAnchor.constraint(equalToConstant: 200).isActive = true
imageView.widthAnchor.constraint(equalToConstant: 200).isActive = true
return imageView
}()
let completeMoreGoalsLabel: UILabel = {
let label = UILabel()
label.text = "Dummytext"
label.textAlignment = .center
return label
}()
now set your stack view with distribution fillProportionally:
lazy var stack: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [image, completeMoreGoalsLabel])
stackView.axis = .vertical
stackView.distribution = .fillProportionally
stackView.translatesAutoresizingMaskIntoConstraints = false
return stackView
}()
in viewDidLoad present your stack and add constraints:
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .darkGray
view.addSubview(stack)
stack.widthAnchor.constraint(equalToConstant: 200).isActive = true
stack.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
stack.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
stack.heightAnchor.constraint(equalToConstant: 250).isActive = true //200 imageHeight + 50 label height
}
I add corner radius on image to make it more cute...
Yes. You simply need to add an ImageView as an arranged subview of your stackview. Just like the labels. Here's the code -
class StackViewController: UIViewController {
var stackView = UIStackView()
var label = UILabel()
var imageView = UIImageView()
override func viewDidLoad() {
super.viewDidLoad()
configStackView()
}
func configStackView() -> Void {
// Add StackView as SubView
view.addSubview(stackView)
// Set StackView properties
stackView.axis = .vertical
stackView.alignment = .center
stackView.distribution = .equalSpacing
// Set imageView as 1st arranged subview of stackview
stackView.addArrangedSubview(imageView)
configImageView()
// Set Label as 2nd arranged subview of stackview
stackView.addArrangedSubview(label)
configLabel()
// Set StackView Constraints
setStackViewCostraints()
}
func setStackViewCostraints() -> Void {
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true
stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true
stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
stackView.heightAnchor.constraint(equalToConstant: 200).isActive = true
}
func configImageView() -> Void {
imageView.image = UIImage(named: "bolt")
imageView.contentMode = .scaleAspectFit
// Set Constraints (ideally in a separate function)
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.widthAnchor.constraint(equalToConstant: 100).isActive = true
}
func configLabel() -> Void {
label.text = "Label"
}
}
Here's the how it renders -

Peculiar top margin in the ImageView added from ChildViewController

I have created a child view controller as below. It has a UIImageView. I added the UIImageView to the view as below.
class SampleChildViewController : UIViewController {
let imageView : UIImageView = {
let imageview = UIImageView()
imageview.translatesAutoresizingMaskIntoConstraints = false
imageview.clipsToBounds = true
imageview.contentMode = .scaleAspectFit
imageview.image = UIImage(named: "cat")
return imageview
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(imageView)
NSLayoutConstraint.activate([
imageView.topAnchor.constraint(equalTo: view.topAnchor),
imageView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 10),
imageView.widthAnchor.constraint(equalToConstant: 150),
imageView.heightAnchor.constraint(equalToConstant: 150)
])
}
}
This is how the parent view controller looks like.
class ViewController: UIViewController {
let child : SampleChildViewController = SampleChildViewController()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.red
child.view.translatesAutoresizingMaskIntoConstraints = false
addChild(child)
child.didMove(toParent: self)
view.addSubview(child.view)
NSLayoutConstraint.activate([
child.view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 8),
child.view.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 8),
child.view.leftAnchor.constraint(equalTo: view.leftAnchor),
child.view.rightAnchor.constraint(equalTo: view.rightAnchor),
])
}
}
Now the problem is I have a strange top margin to the imageview as shown below. How to fix it?
problem is with imageview.contentMode = .scaleAspectFit. The boundary you see for the image is not the real boundary. Set the content mode as imageview.contentMode = .scaleAspectFill as it'll fill the whole view.
It should look something below
let imageView : UIImageView = {
let imageview = UIImageView()
imageview.translatesAutoresizingMaskIntoConstraints = false
imageview.clipsToBounds = true
imageview.contentMode = .scaleAspectFill
imageview.image = UIImage(named: "cat")
return imageview
}()

iOS autolayout locating images at the same line with same ration for each views

I am working on studying iOS autolayout
However, which constraints and functions should I use for making those views have the same location.
I mean, I want to locate those two UIImageView at center like the first picture. But, whenever I change the UIView, they go down and down... what should I do?
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
let firstView:UIImageView = {
let imageView = UIImageView()
imageView.image = #imageLiteral(resourceName: "angry").withRenderingMode(.alwaysOriginal)
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
let secondView:UIImageView = {
let imageView = UIImageView()
imageView.image = #imageLiteral(resourceName: "crying").withRenderingMode(.alwaysOriginal)
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
let thirdView:UIImageView = {
let imageView = UIImageView()
imageView.image = #imageLiteral(resourceName: "heartEmpty").withRenderingMode(.alwaysOriginal)
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
let fourthView:UIImageView = {
let imageView = UIImageView()
imageView.image = #imageLiteral(resourceName: "joy").withRenderingMode(.alwaysOriginal)
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
func setupViews() {
view.addSubview(firstView)
// setup first view
firstView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
firstView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
firstView.widthAnchor.constraint(equalToConstant: 80).isActive = true
firstView.heightAnchor.constraint(equalToConstant: 80).isActive = true
view.addSubview(secondView)
// setup second view
secondView.leftAnchor.constraint(equalTo: firstView.rightAnchor, constant: 20).isActive = true
secondView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
secondView.widthAnchor.constraint(equalToConstant: 80).isActive = true
secondView.heightAnchor.constraint(equalToConstant: 80).isActive = true
view.addSubview(thirdView)
thirdView.leftAnchor.constraint(equalTo: secondView.rightAnchor, constant: 20).isActive = true
thirdView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
thirdView.widthAnchor.constraint(equalToConstant: 80).isActive = true
thirdView.heightAnchor.constraint(equalToConstant: 80).isActive = true
view.addSubview(fourthView)
fourthView.leftAnchor.constraint(equalTo: thirdView.rightAnchor, constant: 20).isActive = true
fourthView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
fourthView.widthAnchor.constraint(equalToConstant: 80).isActive = true
fourthView.heightAnchor.constraint(equalToConstant: 80).isActive = true
}
}
Hello My Friend You Can Make It By Code Or By Storyboard using stack view i will show you by code below hope this help you
import UIKit
class ViewController: UIViewController {
let firstView:UIImageView = {
let imageView = UIImageView()
imageView.image = #imageLiteral(resourceName: "MyImage").withRenderingMode(.alwaysOriginal)
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
let secondView:UIImageView = {
let imageView = UIImageView()
imageView.image = #imageLiteral(resourceName: "image").withRenderingMode(.alwaysOriginal)
imageView.clipsToBounds = true
imageView.contentMode = .scaleAspectFill
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
override func viewDidLoad() {
super.viewDidLoad()
setupViews()
}
func setupViews() {
view.addSubview(firstView)
// setup first view
firstView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
firstView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
firstView.widthAnchor.constraint(equalToConstant: 80).isActive = true
firstView.heightAnchor.constraint(equalToConstant: 80).isActive = true
view.addSubview(secondView)
// setup second view
secondView.leftAnchor.constraint(equalTo: firstView.rightAnchor, constant: 20).isActive = true
secondView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
secondView.widthAnchor.constraint(equalToConstant: 80).isActive = true
secondView.heightAnchor.constraint(equalToConstant: 80).isActive = true
}
}
Follow these Steps, you can do it in Storyboard.
1 - Select first Image, align it horizontally and vertically in container by giving it constraints using the "align" tab which is usually located at the bottom-right corner of the storyboard window.
2 - Now, select the first image and goto Size Inspector.Scroll down to it's constraints and there will be a constraint named as "Align Center X To : SuperView".
3 - There will be an "Edit" label right beside it.Click on it, and a popover will show up.
4 - in the popover , in the first Line it will show Constant = 0.
5 - Now here's the fun part, if you put negative value in it , say "-20" it will move 20 spaces to the left.Similarly, if you put "20", it will move 20 spaces to the right.
Now, do the same for the second image until you have achieved your result. Both the images will now be in the centre of the screen.
I am new to IOS as Well, but this worked for me and I hope it works for u as well. :-)

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