iOS CustomView With AutoLayout in navigationItem not receiving clicks












0














I created a custom view for navigationItem but somehow it is not receiving any click events:



The code for customView is below



class CustomNavigationView: UIView {

let backButton: UIButton = {
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "icon_back", in: Bundle.main, compatibleWith: nil), for: .normal)
button.isUserInteractionEnabled = true
return button
}()

var profileImage: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(named: "icon_back", in: Bundle.main, compatibleWith: nil)
return imageView
}()

var profileName: UILabel = {
let label = UILabel()
label.text = "No Name"
label.font = UIFont(name: "HelveticaNeue", size: 16) ?? UIFont.systemFont(ofSize: 16)
label.textColor = UIColor(red: 96, green: 94, blue: 94)
return label
}()

var onlineStatusIcon: UIView = {
let view = UIView()
view.backgroundColor = UIColor(28, green: 222, blue: 20)
return view
}()

var onlineStatusText: UILabel = {
let label = UILabel()
label.text = "Online"
label.font = UIFont(name: "HelveticaNeue", size: 12) ?? UIFont.systemFont(ofSize: 12)
label.textColor = UIColor(red: 113, green: 110, blue: 110)
return label
}()

lazy var profileView: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [self.profileName, self.onlineStatusText])
stackView.alignment = .fill
stackView.axis = .vertical
stackView.distribution = .fillEqually
stackView.spacing = 2
return stackView
}()

@objc func backButtonClicked(_ sender: UIButton) {
print("Back Button click successfully")
}

private func setupConstraints() {
self.addViewsForAutolayout(views: [backButton, profileImage, onlineStatusIcon, profileView])
//Setup constraints
backButton.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 5).isActive = true
backButton.topAnchor.constraint(equalTo: self.topAnchor, constant: 10).isActive = true
backButton.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -10).isActive = true
backButton.widthAnchor.constraint(equalToConstant: 20).isActive = true

profileImage.leadingAnchor.constraint(equalTo: backButton.trailingAnchor, constant: 20).isActive = true
profileImage.topAnchor.constraint(equalTo: self.topAnchor, constant: 5).isActive = true
profileImage.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -5).isActive = true
profileImage.widthAnchor.constraint(equalToConstant: 35).isActive = true
profileImage.layer.cornerRadius = 18
profileImage.clipsToBounds = true

onlineStatusIcon.bottomAnchor.constraint(equalTo: profileImage.bottomAnchor, constant: 0).isActive = true
onlineStatusIcon.leadingAnchor.constraint(equalTo: profileImage.trailingAnchor, constant: -8).isActive = true
onlineStatusIcon.widthAnchor.constraint(equalToConstant: 10).isActive = true
onlineStatusIcon.heightAnchor.constraint(equalToConstant: 10).isActive = true
onlineStatusIcon.layer.cornerRadius = 5
onlineStatusIcon.clipsToBounds = true

profileView.leadingAnchor.constraint(equalTo: profileImage.trailingAnchor, constant: 5).isActive = true
profileView.topAnchor.constraint(equalTo: profileImage.topAnchor).isActive = true
profileView.bottomAnchor.constraint(equalTo: profileImage.bottomAnchor).isActive = true

}

required init() {
super.init(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 40))
setupConstraints()
addButtonTarget()
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

func addButtonTarget() {
// Setup button callback
backButton.addTarget(self, action: #selector(backButtonClicked(_:)), for: .touchUpInside)

print("Target added")
}
}


And I am setting this view as NavigationbarLeft button Item in my view Controller:



class ViewController:  UIViewController {

override func viewDidLoad() {
super.viewDidLoad()
let customView = CustomNavigationView()
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: customView)
}
}


The view is displaying correctly but the clicks are not working at all.
I used view debugging to check if some other layer is on top of this which might be causing problem but nothing of that sort is present.
I also checked backButton frame when adding the target using debug points.



Is there any solution for this problem. Does autolayout not work with custom view in navigation item? Or is there something that I am missing.



You can run the above piece of code and see that the clicks are not working.



This somehow appears to be related to auto layout. If I hardcode the frame position then clicks are working.



class CustomNavigationView: UIView {

let backButton: UIButton = {
let button = UIButton(frame: CGRect(x: 5, y: 5, width: 30, height: 30))
button.setImage(UIImage(named: "icon_back", in: Bundle.kommunicate, compatibleWith: nil), for: .normal)
button.isUserInteractionEnabled = true
return button
}()

var profileImage: UIImageView = {
let imageView = UIImageView(frame: CGRect(x: 40, y: 5, width: 30, height: 30))
imageView.image = UIImage(named: "icon_back", in: Bundle.kommunicate, compatibleWith: nil)
return imageView
}()

var profileName: UILabel = {
let label = UILabel(frame: CGRect(x: 80, y: 5, width: 50, height: 15))
label.text = "No Name"
label.font = UIFont(name: "HelveticaNeue", size: 16) ?? UIFont.systemFont(ofSize: 16)
label.textColor = UIColor(red: 96, green: 94, blue: 94)
return label
}()

var onlineStatusIcon: UIView = {
let view = UIView(frame: CGRect(x: 65, y: 30, width: 10, height: 10))
view.backgroundColor = UIColor(28, green: 222, blue: 20)
return view
}()

var onlineStatusText: UILabel = {
let label = UILabel(frame: CGRect(x: 80, y: 25, width: 50, height: 10))
label.text = "Online"
label.font = UIFont(name: "HelveticaNeue", size: 12) ?? UIFont.systemFont(ofSize: 12)
label.textColor = UIColor(red: 113, green: 110, blue: 110)
return label
}()

lazy var profileView: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [self.profileName, self.onlineStatusText])
stackView.alignment = .fill
stackView.axis = .vertical
stackView.distribution = .fillEqually
stackView.spacing = 2
return stackView
}()

@objc func backButtonClicked(_ sender: UIButton) {
print("Back button is successfully called")
}

private func setupConstraints() {
self.addSubview(backButton)
self.addSubview(profileImage)
self.addSubview(onlineStatusIcon)
self.addSubview(profileView)
}

required init() {
super.init(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 40))
setupConstraints()
addButtonTarget()
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

func addButtonTarget() {
// Setup button callback
backButton.addTarget(self, action: #selector(backButtonClicked(_:)), for: .touchUpInside)

print("Target added")
}
}









share|improve this question
























  • you have addded custom view inside leftBarButtonItem so you can not get clicked of button inside custom view
    – Jatin Kathrotiya
    Nov 21 at 8:52










  • @JatinKathrotiya I think This is the way you add a customView to a navigationItem. And If you read the question, I have stated it is not working with autolayout. If I try hardcoding frames of every view inside customnavigationView then the click would work.
    – Shivam Pokhriyal
    Nov 21 at 8:56










  • Try to addTarget to backButton in your viewController. It would help. But don't ask me why :) Someone else maybe would explain why.
    – DennyDog
    Nov 21 at 10:08










  • @DennyDog Tried it, I called addButtonTarget from viewDidLoad of viewController. Still not working. Did you tried yourself?
    – shivam pokhriyal
    Nov 21 at 11:03
















0














I created a custom view for navigationItem but somehow it is not receiving any click events:



The code for customView is below



class CustomNavigationView: UIView {

let backButton: UIButton = {
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "icon_back", in: Bundle.main, compatibleWith: nil), for: .normal)
button.isUserInteractionEnabled = true
return button
}()

var profileImage: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(named: "icon_back", in: Bundle.main, compatibleWith: nil)
return imageView
}()

var profileName: UILabel = {
let label = UILabel()
label.text = "No Name"
label.font = UIFont(name: "HelveticaNeue", size: 16) ?? UIFont.systemFont(ofSize: 16)
label.textColor = UIColor(red: 96, green: 94, blue: 94)
return label
}()

var onlineStatusIcon: UIView = {
let view = UIView()
view.backgroundColor = UIColor(28, green: 222, blue: 20)
return view
}()

var onlineStatusText: UILabel = {
let label = UILabel()
label.text = "Online"
label.font = UIFont(name: "HelveticaNeue", size: 12) ?? UIFont.systemFont(ofSize: 12)
label.textColor = UIColor(red: 113, green: 110, blue: 110)
return label
}()

lazy var profileView: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [self.profileName, self.onlineStatusText])
stackView.alignment = .fill
stackView.axis = .vertical
stackView.distribution = .fillEqually
stackView.spacing = 2
return stackView
}()

@objc func backButtonClicked(_ sender: UIButton) {
print("Back Button click successfully")
}

private func setupConstraints() {
self.addViewsForAutolayout(views: [backButton, profileImage, onlineStatusIcon, profileView])
//Setup constraints
backButton.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 5).isActive = true
backButton.topAnchor.constraint(equalTo: self.topAnchor, constant: 10).isActive = true
backButton.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -10).isActive = true
backButton.widthAnchor.constraint(equalToConstant: 20).isActive = true

profileImage.leadingAnchor.constraint(equalTo: backButton.trailingAnchor, constant: 20).isActive = true
profileImage.topAnchor.constraint(equalTo: self.topAnchor, constant: 5).isActive = true
profileImage.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -5).isActive = true
profileImage.widthAnchor.constraint(equalToConstant: 35).isActive = true
profileImage.layer.cornerRadius = 18
profileImage.clipsToBounds = true

onlineStatusIcon.bottomAnchor.constraint(equalTo: profileImage.bottomAnchor, constant: 0).isActive = true
onlineStatusIcon.leadingAnchor.constraint(equalTo: profileImage.trailingAnchor, constant: -8).isActive = true
onlineStatusIcon.widthAnchor.constraint(equalToConstant: 10).isActive = true
onlineStatusIcon.heightAnchor.constraint(equalToConstant: 10).isActive = true
onlineStatusIcon.layer.cornerRadius = 5
onlineStatusIcon.clipsToBounds = true

profileView.leadingAnchor.constraint(equalTo: profileImage.trailingAnchor, constant: 5).isActive = true
profileView.topAnchor.constraint(equalTo: profileImage.topAnchor).isActive = true
profileView.bottomAnchor.constraint(equalTo: profileImage.bottomAnchor).isActive = true

}

required init() {
super.init(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 40))
setupConstraints()
addButtonTarget()
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

func addButtonTarget() {
// Setup button callback
backButton.addTarget(self, action: #selector(backButtonClicked(_:)), for: .touchUpInside)

print("Target added")
}
}


And I am setting this view as NavigationbarLeft button Item in my view Controller:



class ViewController:  UIViewController {

override func viewDidLoad() {
super.viewDidLoad()
let customView = CustomNavigationView()
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: customView)
}
}


The view is displaying correctly but the clicks are not working at all.
I used view debugging to check if some other layer is on top of this which might be causing problem but nothing of that sort is present.
I also checked backButton frame when adding the target using debug points.



Is there any solution for this problem. Does autolayout not work with custom view in navigation item? Or is there something that I am missing.



You can run the above piece of code and see that the clicks are not working.



This somehow appears to be related to auto layout. If I hardcode the frame position then clicks are working.



class CustomNavigationView: UIView {

let backButton: UIButton = {
let button = UIButton(frame: CGRect(x: 5, y: 5, width: 30, height: 30))
button.setImage(UIImage(named: "icon_back", in: Bundle.kommunicate, compatibleWith: nil), for: .normal)
button.isUserInteractionEnabled = true
return button
}()

var profileImage: UIImageView = {
let imageView = UIImageView(frame: CGRect(x: 40, y: 5, width: 30, height: 30))
imageView.image = UIImage(named: "icon_back", in: Bundle.kommunicate, compatibleWith: nil)
return imageView
}()

var profileName: UILabel = {
let label = UILabel(frame: CGRect(x: 80, y: 5, width: 50, height: 15))
label.text = "No Name"
label.font = UIFont(name: "HelveticaNeue", size: 16) ?? UIFont.systemFont(ofSize: 16)
label.textColor = UIColor(red: 96, green: 94, blue: 94)
return label
}()

var onlineStatusIcon: UIView = {
let view = UIView(frame: CGRect(x: 65, y: 30, width: 10, height: 10))
view.backgroundColor = UIColor(28, green: 222, blue: 20)
return view
}()

var onlineStatusText: UILabel = {
let label = UILabel(frame: CGRect(x: 80, y: 25, width: 50, height: 10))
label.text = "Online"
label.font = UIFont(name: "HelveticaNeue", size: 12) ?? UIFont.systemFont(ofSize: 12)
label.textColor = UIColor(red: 113, green: 110, blue: 110)
return label
}()

lazy var profileView: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [self.profileName, self.onlineStatusText])
stackView.alignment = .fill
stackView.axis = .vertical
stackView.distribution = .fillEqually
stackView.spacing = 2
return stackView
}()

@objc func backButtonClicked(_ sender: UIButton) {
print("Back button is successfully called")
}

private func setupConstraints() {
self.addSubview(backButton)
self.addSubview(profileImage)
self.addSubview(onlineStatusIcon)
self.addSubview(profileView)
}

required init() {
super.init(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 40))
setupConstraints()
addButtonTarget()
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

func addButtonTarget() {
// Setup button callback
backButton.addTarget(self, action: #selector(backButtonClicked(_:)), for: .touchUpInside)

print("Target added")
}
}









share|improve this question
























  • you have addded custom view inside leftBarButtonItem so you can not get clicked of button inside custom view
    – Jatin Kathrotiya
    Nov 21 at 8:52










  • @JatinKathrotiya I think This is the way you add a customView to a navigationItem. And If you read the question, I have stated it is not working with autolayout. If I try hardcoding frames of every view inside customnavigationView then the click would work.
    – Shivam Pokhriyal
    Nov 21 at 8:56










  • Try to addTarget to backButton in your viewController. It would help. But don't ask me why :) Someone else maybe would explain why.
    – DennyDog
    Nov 21 at 10:08










  • @DennyDog Tried it, I called addButtonTarget from viewDidLoad of viewController. Still not working. Did you tried yourself?
    – shivam pokhriyal
    Nov 21 at 11:03














0












0








0







I created a custom view for navigationItem but somehow it is not receiving any click events:



The code for customView is below



class CustomNavigationView: UIView {

let backButton: UIButton = {
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "icon_back", in: Bundle.main, compatibleWith: nil), for: .normal)
button.isUserInteractionEnabled = true
return button
}()

var profileImage: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(named: "icon_back", in: Bundle.main, compatibleWith: nil)
return imageView
}()

var profileName: UILabel = {
let label = UILabel()
label.text = "No Name"
label.font = UIFont(name: "HelveticaNeue", size: 16) ?? UIFont.systemFont(ofSize: 16)
label.textColor = UIColor(red: 96, green: 94, blue: 94)
return label
}()

var onlineStatusIcon: UIView = {
let view = UIView()
view.backgroundColor = UIColor(28, green: 222, blue: 20)
return view
}()

var onlineStatusText: UILabel = {
let label = UILabel()
label.text = "Online"
label.font = UIFont(name: "HelveticaNeue", size: 12) ?? UIFont.systemFont(ofSize: 12)
label.textColor = UIColor(red: 113, green: 110, blue: 110)
return label
}()

lazy var profileView: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [self.profileName, self.onlineStatusText])
stackView.alignment = .fill
stackView.axis = .vertical
stackView.distribution = .fillEqually
stackView.spacing = 2
return stackView
}()

@objc func backButtonClicked(_ sender: UIButton) {
print("Back Button click successfully")
}

private func setupConstraints() {
self.addViewsForAutolayout(views: [backButton, profileImage, onlineStatusIcon, profileView])
//Setup constraints
backButton.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 5).isActive = true
backButton.topAnchor.constraint(equalTo: self.topAnchor, constant: 10).isActive = true
backButton.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -10).isActive = true
backButton.widthAnchor.constraint(equalToConstant: 20).isActive = true

profileImage.leadingAnchor.constraint(equalTo: backButton.trailingAnchor, constant: 20).isActive = true
profileImage.topAnchor.constraint(equalTo: self.topAnchor, constant: 5).isActive = true
profileImage.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -5).isActive = true
profileImage.widthAnchor.constraint(equalToConstant: 35).isActive = true
profileImage.layer.cornerRadius = 18
profileImage.clipsToBounds = true

onlineStatusIcon.bottomAnchor.constraint(equalTo: profileImage.bottomAnchor, constant: 0).isActive = true
onlineStatusIcon.leadingAnchor.constraint(equalTo: profileImage.trailingAnchor, constant: -8).isActive = true
onlineStatusIcon.widthAnchor.constraint(equalToConstant: 10).isActive = true
onlineStatusIcon.heightAnchor.constraint(equalToConstant: 10).isActive = true
onlineStatusIcon.layer.cornerRadius = 5
onlineStatusIcon.clipsToBounds = true

profileView.leadingAnchor.constraint(equalTo: profileImage.trailingAnchor, constant: 5).isActive = true
profileView.topAnchor.constraint(equalTo: profileImage.topAnchor).isActive = true
profileView.bottomAnchor.constraint(equalTo: profileImage.bottomAnchor).isActive = true

}

required init() {
super.init(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 40))
setupConstraints()
addButtonTarget()
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

func addButtonTarget() {
// Setup button callback
backButton.addTarget(self, action: #selector(backButtonClicked(_:)), for: .touchUpInside)

print("Target added")
}
}


And I am setting this view as NavigationbarLeft button Item in my view Controller:



class ViewController:  UIViewController {

override func viewDidLoad() {
super.viewDidLoad()
let customView = CustomNavigationView()
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: customView)
}
}


The view is displaying correctly but the clicks are not working at all.
I used view debugging to check if some other layer is on top of this which might be causing problem but nothing of that sort is present.
I also checked backButton frame when adding the target using debug points.



Is there any solution for this problem. Does autolayout not work with custom view in navigation item? Or is there something that I am missing.



You can run the above piece of code and see that the clicks are not working.



This somehow appears to be related to auto layout. If I hardcode the frame position then clicks are working.



class CustomNavigationView: UIView {

let backButton: UIButton = {
let button = UIButton(frame: CGRect(x: 5, y: 5, width: 30, height: 30))
button.setImage(UIImage(named: "icon_back", in: Bundle.kommunicate, compatibleWith: nil), for: .normal)
button.isUserInteractionEnabled = true
return button
}()

var profileImage: UIImageView = {
let imageView = UIImageView(frame: CGRect(x: 40, y: 5, width: 30, height: 30))
imageView.image = UIImage(named: "icon_back", in: Bundle.kommunicate, compatibleWith: nil)
return imageView
}()

var profileName: UILabel = {
let label = UILabel(frame: CGRect(x: 80, y: 5, width: 50, height: 15))
label.text = "No Name"
label.font = UIFont(name: "HelveticaNeue", size: 16) ?? UIFont.systemFont(ofSize: 16)
label.textColor = UIColor(red: 96, green: 94, blue: 94)
return label
}()

var onlineStatusIcon: UIView = {
let view = UIView(frame: CGRect(x: 65, y: 30, width: 10, height: 10))
view.backgroundColor = UIColor(28, green: 222, blue: 20)
return view
}()

var onlineStatusText: UILabel = {
let label = UILabel(frame: CGRect(x: 80, y: 25, width: 50, height: 10))
label.text = "Online"
label.font = UIFont(name: "HelveticaNeue", size: 12) ?? UIFont.systemFont(ofSize: 12)
label.textColor = UIColor(red: 113, green: 110, blue: 110)
return label
}()

lazy var profileView: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [self.profileName, self.onlineStatusText])
stackView.alignment = .fill
stackView.axis = .vertical
stackView.distribution = .fillEqually
stackView.spacing = 2
return stackView
}()

@objc func backButtonClicked(_ sender: UIButton) {
print("Back button is successfully called")
}

private func setupConstraints() {
self.addSubview(backButton)
self.addSubview(profileImage)
self.addSubview(onlineStatusIcon)
self.addSubview(profileView)
}

required init() {
super.init(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 40))
setupConstraints()
addButtonTarget()
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

func addButtonTarget() {
// Setup button callback
backButton.addTarget(self, action: #selector(backButtonClicked(_:)), for: .touchUpInside)

print("Target added")
}
}









share|improve this question















I created a custom view for navigationItem but somehow it is not receiving any click events:



The code for customView is below



class CustomNavigationView: UIView {

let backButton: UIButton = {
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "icon_back", in: Bundle.main, compatibleWith: nil), for: .normal)
button.isUserInteractionEnabled = true
return button
}()

var profileImage: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(named: "icon_back", in: Bundle.main, compatibleWith: nil)
return imageView
}()

var profileName: UILabel = {
let label = UILabel()
label.text = "No Name"
label.font = UIFont(name: "HelveticaNeue", size: 16) ?? UIFont.systemFont(ofSize: 16)
label.textColor = UIColor(red: 96, green: 94, blue: 94)
return label
}()

var onlineStatusIcon: UIView = {
let view = UIView()
view.backgroundColor = UIColor(28, green: 222, blue: 20)
return view
}()

var onlineStatusText: UILabel = {
let label = UILabel()
label.text = "Online"
label.font = UIFont(name: "HelveticaNeue", size: 12) ?? UIFont.systemFont(ofSize: 12)
label.textColor = UIColor(red: 113, green: 110, blue: 110)
return label
}()

lazy var profileView: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [self.profileName, self.onlineStatusText])
stackView.alignment = .fill
stackView.axis = .vertical
stackView.distribution = .fillEqually
stackView.spacing = 2
return stackView
}()

@objc func backButtonClicked(_ sender: UIButton) {
print("Back Button click successfully")
}

private func setupConstraints() {
self.addViewsForAutolayout(views: [backButton, profileImage, onlineStatusIcon, profileView])
//Setup constraints
backButton.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 5).isActive = true
backButton.topAnchor.constraint(equalTo: self.topAnchor, constant: 10).isActive = true
backButton.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -10).isActive = true
backButton.widthAnchor.constraint(equalToConstant: 20).isActive = true

profileImage.leadingAnchor.constraint(equalTo: backButton.trailingAnchor, constant: 20).isActive = true
profileImage.topAnchor.constraint(equalTo: self.topAnchor, constant: 5).isActive = true
profileImage.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -5).isActive = true
profileImage.widthAnchor.constraint(equalToConstant: 35).isActive = true
profileImage.layer.cornerRadius = 18
profileImage.clipsToBounds = true

onlineStatusIcon.bottomAnchor.constraint(equalTo: profileImage.bottomAnchor, constant: 0).isActive = true
onlineStatusIcon.leadingAnchor.constraint(equalTo: profileImage.trailingAnchor, constant: -8).isActive = true
onlineStatusIcon.widthAnchor.constraint(equalToConstant: 10).isActive = true
onlineStatusIcon.heightAnchor.constraint(equalToConstant: 10).isActive = true
onlineStatusIcon.layer.cornerRadius = 5
onlineStatusIcon.clipsToBounds = true

profileView.leadingAnchor.constraint(equalTo: profileImage.trailingAnchor, constant: 5).isActive = true
profileView.topAnchor.constraint(equalTo: profileImage.topAnchor).isActive = true
profileView.bottomAnchor.constraint(equalTo: profileImage.bottomAnchor).isActive = true

}

required init() {
super.init(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 40))
setupConstraints()
addButtonTarget()
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

func addButtonTarget() {
// Setup button callback
backButton.addTarget(self, action: #selector(backButtonClicked(_:)), for: .touchUpInside)

print("Target added")
}
}


And I am setting this view as NavigationbarLeft button Item in my view Controller:



class ViewController:  UIViewController {

override func viewDidLoad() {
super.viewDidLoad()
let customView = CustomNavigationView()
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: customView)
}
}


The view is displaying correctly but the clicks are not working at all.
I used view debugging to check if some other layer is on top of this which might be causing problem but nothing of that sort is present.
I also checked backButton frame when adding the target using debug points.



Is there any solution for this problem. Does autolayout not work with custom view in navigation item? Or is there something that I am missing.



You can run the above piece of code and see that the clicks are not working.



This somehow appears to be related to auto layout. If I hardcode the frame position then clicks are working.



class CustomNavigationView: UIView {

let backButton: UIButton = {
let button = UIButton(frame: CGRect(x: 5, y: 5, width: 30, height: 30))
button.setImage(UIImage(named: "icon_back", in: Bundle.kommunicate, compatibleWith: nil), for: .normal)
button.isUserInteractionEnabled = true
return button
}()

var profileImage: UIImageView = {
let imageView = UIImageView(frame: CGRect(x: 40, y: 5, width: 30, height: 30))
imageView.image = UIImage(named: "icon_back", in: Bundle.kommunicate, compatibleWith: nil)
return imageView
}()

var profileName: UILabel = {
let label = UILabel(frame: CGRect(x: 80, y: 5, width: 50, height: 15))
label.text = "No Name"
label.font = UIFont(name: "HelveticaNeue", size: 16) ?? UIFont.systemFont(ofSize: 16)
label.textColor = UIColor(red: 96, green: 94, blue: 94)
return label
}()

var onlineStatusIcon: UIView = {
let view = UIView(frame: CGRect(x: 65, y: 30, width: 10, height: 10))
view.backgroundColor = UIColor(28, green: 222, blue: 20)
return view
}()

var onlineStatusText: UILabel = {
let label = UILabel(frame: CGRect(x: 80, y: 25, width: 50, height: 10))
label.text = "Online"
label.font = UIFont(name: "HelveticaNeue", size: 12) ?? UIFont.systemFont(ofSize: 12)
label.textColor = UIColor(red: 113, green: 110, blue: 110)
return label
}()

lazy var profileView: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [self.profileName, self.onlineStatusText])
stackView.alignment = .fill
stackView.axis = .vertical
stackView.distribution = .fillEqually
stackView.spacing = 2
return stackView
}()

@objc func backButtonClicked(_ sender: UIButton) {
print("Back button is successfully called")
}

private func setupConstraints() {
self.addSubview(backButton)
self.addSubview(profileImage)
self.addSubview(onlineStatusIcon)
self.addSubview(profileView)
}

required init() {
super.init(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 40))
setupConstraints()
addButtonTarget()
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

func addButtonTarget() {
// Setup button callback
backButton.addTarget(self, action: #selector(backButtonClicked(_:)), for: .touchUpInside)

print("Target added")
}
}






ios swift uibutton customization uinavigationitem






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 21 at 12:29

























asked Nov 21 at 8:14









shivam pokhriyal

358




358












  • you have addded custom view inside leftBarButtonItem so you can not get clicked of button inside custom view
    – Jatin Kathrotiya
    Nov 21 at 8:52










  • @JatinKathrotiya I think This is the way you add a customView to a navigationItem. And If you read the question, I have stated it is not working with autolayout. If I try hardcoding frames of every view inside customnavigationView then the click would work.
    – Shivam Pokhriyal
    Nov 21 at 8:56










  • Try to addTarget to backButton in your viewController. It would help. But don't ask me why :) Someone else maybe would explain why.
    – DennyDog
    Nov 21 at 10:08










  • @DennyDog Tried it, I called addButtonTarget from viewDidLoad of viewController. Still not working. Did you tried yourself?
    – shivam pokhriyal
    Nov 21 at 11:03


















  • you have addded custom view inside leftBarButtonItem so you can not get clicked of button inside custom view
    – Jatin Kathrotiya
    Nov 21 at 8:52










  • @JatinKathrotiya I think This is the way you add a customView to a navigationItem. And If you read the question, I have stated it is not working with autolayout. If I try hardcoding frames of every view inside customnavigationView then the click would work.
    – Shivam Pokhriyal
    Nov 21 at 8:56










  • Try to addTarget to backButton in your viewController. It would help. But don't ask me why :) Someone else maybe would explain why.
    – DennyDog
    Nov 21 at 10:08










  • @DennyDog Tried it, I called addButtonTarget from viewDidLoad of viewController. Still not working. Did you tried yourself?
    – shivam pokhriyal
    Nov 21 at 11:03
















you have addded custom view inside leftBarButtonItem so you can not get clicked of button inside custom view
– Jatin Kathrotiya
Nov 21 at 8:52




you have addded custom view inside leftBarButtonItem so you can not get clicked of button inside custom view
– Jatin Kathrotiya
Nov 21 at 8:52












@JatinKathrotiya I think This is the way you add a customView to a navigationItem. And If you read the question, I have stated it is not working with autolayout. If I try hardcoding frames of every view inside customnavigationView then the click would work.
– Shivam Pokhriyal
Nov 21 at 8:56




@JatinKathrotiya I think This is the way you add a customView to a navigationItem. And If you read the question, I have stated it is not working with autolayout. If I try hardcoding frames of every view inside customnavigationView then the click would work.
– Shivam Pokhriyal
Nov 21 at 8:56












Try to addTarget to backButton in your viewController. It would help. But don't ask me why :) Someone else maybe would explain why.
– DennyDog
Nov 21 at 10:08




Try to addTarget to backButton in your viewController. It would help. But don't ask me why :) Someone else maybe would explain why.
– DennyDog
Nov 21 at 10:08












@DennyDog Tried it, I called addButtonTarget from viewDidLoad of viewController. Still not working. Did you tried yourself?
– shivam pokhriyal
Nov 21 at 11:03




@DennyDog Tried it, I called addButtonTarget from viewDidLoad of viewController. Still not working. Did you tried yourself?
– shivam pokhriyal
Nov 21 at 11:03












1 Answer
1






active

oldest

votes


















2














The problem is with the manually added constraints that you added.
Using the view debugger the width of CustomNavigationView after it is added to the bar is 0.



In order to force the container to expand, add the following constraint in setupConstraints():



profileView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true


Now that the container expands to match it's contents, the touch events should be propagated to the button as expected.






share|improve this answer























  • Thank you so much. I tried view debug myself but missed this.
    – shivam pokhriyal
    Nov 21 at 13:03











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53407723%2fios-customview-with-autolayout-in-navigationitem-not-receiving-clicks%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









2














The problem is with the manually added constraints that you added.
Using the view debugger the width of CustomNavigationView after it is added to the bar is 0.



In order to force the container to expand, add the following constraint in setupConstraints():



profileView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true


Now that the container expands to match it's contents, the touch events should be propagated to the button as expected.






share|improve this answer























  • Thank you so much. I tried view debug myself but missed this.
    – shivam pokhriyal
    Nov 21 at 13:03
















2














The problem is with the manually added constraints that you added.
Using the view debugger the width of CustomNavigationView after it is added to the bar is 0.



In order to force the container to expand, add the following constraint in setupConstraints():



profileView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true


Now that the container expands to match it's contents, the touch events should be propagated to the button as expected.






share|improve this answer























  • Thank you so much. I tried view debug myself but missed this.
    – shivam pokhriyal
    Nov 21 at 13:03














2












2








2






The problem is with the manually added constraints that you added.
Using the view debugger the width of CustomNavigationView after it is added to the bar is 0.



In order to force the container to expand, add the following constraint in setupConstraints():



profileView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true


Now that the container expands to match it's contents, the touch events should be propagated to the button as expected.






share|improve this answer














The problem is with the manually added constraints that you added.
Using the view debugger the width of CustomNavigationView after it is added to the bar is 0.



In order to force the container to expand, add the following constraint in setupConstraints():



profileView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true


Now that the container expands to match it's contents, the touch events should be propagated to the button as expected.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 21 at 13:57

























answered Nov 21 at 12:54









Aris

1,293613




1,293613












  • Thank you so much. I tried view debug myself but missed this.
    – shivam pokhriyal
    Nov 21 at 13:03


















  • Thank you so much. I tried view debug myself but missed this.
    – shivam pokhriyal
    Nov 21 at 13:03
















Thank you so much. I tried view debug myself but missed this.
– shivam pokhriyal
Nov 21 at 13:03




Thank you so much. I tried view debug myself but missed this.
– shivam pokhriyal
Nov 21 at 13:03


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53407723%2fios-customview-with-autolayout-in-navigationitem-not-receiving-clicks%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

404 Error Contact Form 7 ajax form submitting

How to know if a Active Directory user can login interactively

Refactoring coordinates for Minecraft Pi buildings written in Python