UITapGestureRecognizer is not working inside the custom UIView - ios

My ViewController looks like follows. Here I am calling my custom view and setting it programmatically. The Problem I am facing is the tap gesture is not working. Even it is not getting called.
This [https://stackoverflow.com/questions/60931438/uitapgesturerecognizer-not-working-with-custom-view-class][1] is also similar to this but I can't understand what is happening in my case. I am Stuck here for hours.
class myViewController : ViewController {
init() {
super.init(nibName: nil, bundle: nil)
self.view.addSubview(self.myView)
self.myView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
self.myView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
lazy var myView : MyCustomView = {
let view = MyCustomView(frame: CGRect(x: 0, y: 0, width: 476.0, height: 398.0))
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
}
My custom view is this.
class MyCustomView : UIView {
override init(frame: CGRect) {
super.init(frame: frame)
self.widthAnchor.constraint(equalToConstant: frame.width).isActive = true
self.heightAnchor.constraint(equalToConstant: frame.height).isActive = true
self.mView.topAnchor.constraint(equalTo: self.topAnchor, constant: 10).isActive = true
self.mView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20).isActive = true
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
private lazy var mView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = UIColor.init(hexString: "#EDEEEF")
view.isUserInteractionEnabled = true
let gesture = UITapGestureRecognizer(target: self, action: #selector(tappedDropDown))
view.addGestureRecognizer(gesture)
return view
}()
#objc func tappedDropDown(sender : UITapGestureRecognizer){
print("Tapped")
}
}

There are numerous issues with the example code that will stop it working, and some that will stop it even compiling (unterminated string literals, trying to set autolayout (AL) constraints without setting TAMIC to false, etc).
But I think* the issue stopping the tap gesture working is that the layout code is a mix of frame sizes and AL constraints and it isn't laying things out the way you believe it is, which means that the custom view's child view isn't receiving the gesture to respond too.
Changing the layout code so that it is all AL makes the tap gesture work without any changes to gesture recogniser or its action method.
I'm assuming the layout you're aiming for is the VC's view with a subview (your CustomView) which in turn has its own subview (your mView, which below I have renamed subView to make it clearer), in a three-tiered pyramid type of stack.
I say 'think' above because I may have corrected some other error in fixing the layout code. I've only corrected the code necessary to get it to compile and give a working UI. I've not intentionally addressed any other issue as they are not relevant to the question.
The code below works in that it lays out the three views (the VC's view, the myView (a CustomView), and the CustomView's subview and adds the tapGestureRecogniser to subView. The gestureRecogniser fires its selector method when tapped. It might not be laid out how you want as it was hard to tell the layout you were trying to achieve, but it does demonstrate that the gestureRecogniser works as expected.
class myViewController : UIViewController {
lazy var myView : MyCustomView = {MyCustomView(frame: .zero)}()
init() {
super.init(nibName: nil, bundle: nil)
view.heightAnchor.constraint(equalToConstant: 600).isActive = true
view.addSubview(myView)
myView.topAnchor.constraint(equalTo: view.topAnchor, constant: 50).isActive = true
myView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -50).isActive = true
myView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -50).isActive = true
myView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 50).isActive = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class MyCustomView : UIView {
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .systemOrange
translatesAutoresizingMaskIntoConstraints = false
addSubview(subView)
subView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: -50).isActive = true
subView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -50).isActive = true
subView.topAnchor.constraint(equalTo: topAnchor, constant: 50).isActive = true
subView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -50).isActive = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private lazy var subView: UIView = {
let view = UIView()
view.backgroundColor = .systemBlue
view.translatesAutoresizingMaskIntoConstraints = false
view.isUserInteractionEnabled = true
let gesture = UITapGestureRecognizer(target: self, action: #selector(tappedDropDown))
view.addGestureRecognizer(gesture)
return view
}()
#objc func tappedDropDown(sender : UITapGestureRecognizer){
print("Tapped")
}
}

I think that the problem is that you have the function tu run outside the ViewController. Just do the following:
class myViewController : ViewController {
#objc func tappedDropDown(sender : UITapGestureRecognizer){
print("Tapped")
}
init() {
super.init(nibName: nil, bundle: nil)
self.view.addSubview(self.myView)
self.myView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
self.myView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
lazy var myView : MyCustomView = {
let view = MyCustomView(frame: CGRect(x: 0, y: 0, width: 476.0, height: 398.0))
view.translatesAutoresizingMaskIntoConstraints = false
let gesture = UITapGestureRecognizer(target: self, action: #selector(tappedDropDown))
view.addGestureRecognizer(gesture)
return view
}()
}
And, remove the lines I added here from your custom class.

Related

safeAreaLayoutGuide guide not working from another viewcontroller

As suggested by some experts like #DonMag , i design the view in a separate controller, while trying to do so , every thing works, but when i use a navigation controller and there is a navigation bar at top, if i try and design in separate controller and then add its view to another controller the safeAreaLayoutGuide does not work and the view is attached to top of screen ignoring the safearea
SOLUTION as per #Mohammad Azam, DonMag solutions works as well , thanks
import UIKit
class NotesDesign: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func commonInit(){
let notesTitle = UITextField()
let notesContent = UITextView()
let font = UIFont(name: "CourierNewPS-ItalicMT", size: 20)
let fontM = UIFontMetrics(forTextStyle: .body)
notesTitle.font = fontM.scaledFont(for: font!)
notesContent.font = fontM.scaledFont(for: font!)
notesTitle.widthAnchor.constraint(greaterThanOrEqualToConstant:250).isActive = true
notesTitle.heightAnchor.constraint(equalToConstant: 30).isActive = true
notesTitle.borderStyle = .line
notesContent.widthAnchor.constraint(greaterThanOrEqualToConstant:250).isActive = true
notesContent.heightAnchor.constraint(greaterThanOrEqualToConstant: 100).isActive = true
notesContent.layer.borderWidth = 1
let notesStack = UIStackView()
notesStack.axis = .vertical
notesStack.spacing = 20
notesStack.alignment = .top
notesStack.distribution = .fill
notesStack.addArrangedSubview(notesTitle)
notesStack.addArrangedSubview(notesContent)
// Do any additional setup after loading the view.
notesStack.translatesAutoresizingMaskIntoConstraints = false
addSubview(notesStack)
notesStack.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor, constant: 10).isActive = true
notesStack.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20).isActive = true
notesStack.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -10).isActive = true
notesStack.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -40).isActive = true
}
}
And where i call it
import UIKit
class AddNotesViewController: UIViewController {
var design = NotesDesign()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
view.addSubview(design)
design.translatesAutoresizingMaskIntoConstraints = false
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Save", style: .plain, target: self, action: #selector(saveData))
}
#objc func saveData() {
}
}
And this is what i get
If you are taking a view from its ViewController and adding it as a subview to another view, you need to constrain it just like you would with any other added subview:
class AddNotesViewController: UIViewController {
var design = NotesViewDesign()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
view.addSubview(design.view)
// a view loaded from a UIViewController has .translatesAutoresizingMaskIntoConstraints = true
design.view.translatesAutoresizingMaskIntoConstraints = false
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
// constrain the loaded view
design.view.topAnchor.constraint(equalTo: g.topAnchor),
design.view.leadingAnchor.constraint(equalTo: g.leadingAnchor),
design.view.trailingAnchor.constraint(equalTo: g.trailingAnchor),
design.view.bottomAnchor.constraint(equalTo: g.bottomAnchor),
])
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Save", style: .plain, target: self, action: #selector(saveData))
}
#objc func saveData() {
}
}

addSubview doesn't work in UIView - Swift Programmatically

I need to add a UIButton as a subview on a UIView but it actually doesn't appear at runtime.
This is my code:
let moreButton : UIButton = {
let button = UIButton()
button.setImage(#imageLiteral(resourceName: "more"), for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(moreButton)
moreButton.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
moreButton.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
moreButton.heightAnchor.constraint(equalToConstant: 30).isActive = true
moreButton.widthAnchor.constraint(equalToConstant: 20).isActive = true
}
The button isn't added eventually to the view. I'm sure this is an easy fix but I can't wrap my head around it.
First of all, make sure you the viewController is showing anything since you're doing it without storyboards, check out this simple tutorial:
https://medium.com/better-programming/creating-a-project-without-storyboard-in-2020-and-without-swifui-82080eb6d13b
If the problem is with that UIButton, try to set up the subviews in viewDidLoad:
final class ViewController: UIViewController {
let cardView = CardView()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(cardView)
/// Constraints
let margins = view.layoutMarginsGuide
cardView.trailingAnchor.constraint(equalTo: margins.trailingAnchor).isActive = true
cardView.leadingAnchor.constraint(equalTo: margins.leadingAnchor).isActive = true
cardView.topAnchor.constraint(equalTo: margins.topAnchor).isActive = true
cardView.heightAnchor.constraint(equalToConstant: 30).isActive = true
cardView.widthAnchor.constraint(equalToConstant: 20).isActive = true
}
}
final class CardView: UIView {
let moreButton : UIButton = {
let button = UIButton()
button.setTitle("Button title", for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
}
override init(frame: CGRect) {
super.init(frame:frame)
self.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(moreButton)
/// Constraints
let margins = self.layoutMarginsGuide
moreButton.trailingAnchor.constraint(equalTo: margins.trailingAnchor).isActive = true
moreButton.leadingAnchor.constraint(equalTo: margins.leadingAnchor).isActive = true
moreButton.topAnchor.constraint(equalTo: margins.topAnchor).isActive = true
moreButton.heightAnchor.constraint(equalToConstant: 30).isActive = true
moreButton.widthAnchor.constraint(equalToConstant: 20).isActive = true
}
}
I've set up margins for the constraints and also added a leadingAnchor constraint, that might have been the issue as well.

self.perform segue causes view to not conform

I have programmatically created a view layout with a content view, when this controller is the initial view controller I get something like this.
:
When I have another view controller and segue to this viewcontroller, I get something like this:
Attached is my View Class:
class TestView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
setupConstraints()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupViews() {
self.addSubview(contentView)
}
func setupConstraints() {
self.translatesAutoresizingMaskIntoConstraints = false
contentView.translatesAutoresizingMaskIntoConstraints = false
contentView.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 0).isActive = true
// check what safearealayoutguide is
if #available(iOS 11.0, *) {
print("IOS11 Screen")
contentView.topAnchor.constraint(equalTo: self.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
} else {
contentView.topAnchor.constraint(equalTo: self.layoutMarginsGuide.topAnchor, constant: 0).isActive = true
}
contentView.rightAnchor.constraint(equalTo: self.layoutMarginsGuide.rightAnchor, constant: 0).isActive = true
if #available(iOS 11.0, *) {
contentView.bottomAnchor.constraint(equalTo: self.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
} else {
contentView.bottomAnchor.constraint(equalTo: self.layoutMarginsGuide.bottomAnchor, constant: 0).isActive = true
}
}
let contentView: UIView = {
let view = UIView(frame: CGRect(x: 100, y: 100, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.width))
//view.layer.backgroundColor = CGColortran
view.layer.borderWidth = 1
view.layer.borderColor = UIColor.green.cgColor
return view
}()
}
then my view controller:
class TestViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func loadView() {
self.view = TestView(frame: UIScreen.main.bounds)
}
}
When this is the only screen in the application, it works. when I add another view controller and do a self.performSegue(withIdentifier: "LoginUser", sender: nil) it seems to break the view. What's going on here?
Comment
self.translatesAutoresizingMaskIntoConstraints = false
as currently you mix setting a frame TestView(frame: UIScreen.main.bounds) with constraints , the above line is used only for a view when you set constraints to it as it invalidates the frame

UIViewController with custom UIView (that includes a button) doesn't recognize taps

When trying to load a custom UIView (BaseHeader.swift) that contains a UIButton into a UIViewController (ViewController.swift) programmatically, the taps on the button are not recognized.
If I extract the code within the custom UIView and paste it directly into the UIViewController, all taps are recognized and working as expected. What am I missing?
At first, I thought it was a problem with not defining a frame size for the UIView after it gets instantiated. I thought that there might be no "hit box" for the button despite it being displayed as intended. After giving the view a frame I still had no luck and tried various other things after googling about for awhile.
The view loads but button taps are not recognized -- see image
ViewController.swift
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.title = "Authentication"
}
override func loadView() {
super.loadView()
let header = BaseHeader()
header.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(header)
NSLayoutConstraint.activate([
header.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
header.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
header.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: -10),
])
}
}
BaseHeader.swift
import UIKit
class BaseHeader: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
func setupView() {
self.isUserInteractionEnabled = true
let avenirFont = UIFont(name: "Avenir", size: 40)
let lightAvenirTitle = avenirFont?.light
let title = UILabel()
title.text = "Title"
title.font = lightAvenirTitle
title.textColor = .black
title.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(title)
NSLayoutConstraint.activate([
title.topAnchor.constraint(equalTo: self.topAnchor, constant: 20),
title.centerXAnchor.constraint(equalTo: self.centerXAnchor)
])
let profile = UIButton()
let profileImage = UIImage(named: "person-icon")
profile.setImage(profileImage, for: .normal)
profile.setImage(UIImage(named: "think-icon"), for: .highlighted)
profile.addTarget(self, action: #selector(profileTapped), for: .touchUpInside)
profile.backgroundColor = .systemBlue
profile.frame.size = CGSize(width: 30, height: 30)
profile.isUserInteractionEnabled = true
profile.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(profile)
NSLayoutConstraint.activate([
profile.centerYAnchor.constraint(equalTo: title.centerYAnchor),
profile.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20),
])
}
#objc func profileTapped(sender: UIButton) {
print("Tapped")
}
}
You forgot set height for BaseHeader
NSLayoutConstraint.activate([
header.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
header.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
header.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: -10),
header.heightAnchor.constraint(equalToConstant: 40) //add more
])
It might be that you are calling the wrong initializer for your custom view and that your setupView() function is not being called. It looks like in the view controller you are calling
let header = BaseHeader()
To initialize the view, but it's this init:
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
That calls your setupView() function and sets up the tap.

Swift: UIStackView of UIControls with selector method that doesn't fire

Introduction
I'm creating an app which uses a custom view in which I have a UIStackView to sort out 5 UIControls. When a user taps one of the UIControls an underscore line gets animated, sliding under the tapped UIControl.
However, for some reason the method/selector for these UIControls no longer gets called. I believe this has to do with that I updated my Mac to the macOS (and Xcode) update released this week (wk.44). (updated from swift 4.2 to swift 4.2.1). Before the updated this animation and selector worked perfectly. But I'm not sure. And I'm now completely stuck on what I'm doing wrong.
Context
I created a playground and scaled down everything as much as I could and the issue persists.
I have tried to define the UIStackView in the global scope of my SetupView class but it doesn't change anything. So I believe it is not an issue of the stackView or its subviews being deallocated?
Below I've provided my UIControl subclass and my SetupView (UIView subclass) that I use. I've created a playground so you may copy paste in Xcode playground to test if you want.
Question
Why doesn't the method goalViewControlTapped(_ sender: SetupViewControl) get called?
Code
import UIKit
import PlaygroundSupport
class SetupViewControl: UIControl {
let titleLabel : UILabel = {
let lbl = UILabel()
lbl.font = UIFont(name: "Futura", size: 14)
lbl.textColor = .white
lbl.backgroundColor = .clear
lbl.textAlignment = .center
lbl.translatesAutoresizingMaskIntoConstraints = false
return lbl
}()
override init(frame: CGRect) {
super.init(frame: frame)
setupLabel()
layer.cornerRadius = 5
}
fileprivate func setupLabel() {
addSubview(titleLabel)
titleLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 5).isActive = true
titleLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -5).isActive = true
titleLabel.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override var isHighlighted: Bool {
didSet {
UIView.animate(withDuration: 0.12) {
self.backgroundColor = self.isHighlighted ? UIColor.lightGray : UIColor.clear
}
}
}
}
class SetupView: UIView {
let dataModel : [String] = ["2 weeks", "1 month", "2 months", "6 months", "1 year"]
var selectionLineCenterX : NSLayoutConstraint!
let selectionLine = UIView()
let labelZero = SetupViewControl()
let labelOne = SetupViewControl()
let labelTwo = SetupViewControl()
let labelThree = SetupViewControl()
let labelFour = SetupViewControl()
let labelFive = SetupViewControl()
lazy var controlArray = [self.labelZero, self.labelOne, self.labelTwo, self.labelThree, self.labelFour, self.labelFive]
init(frame: CGRect, color: UIColor) {
super.init(frame: frame)
self.backgroundColor = color
setupView()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
fileprivate func setupView() {
layer.cornerRadius = 0
layer.borderColor = UIColor.black.cgColor
layer.borderWidth = 1
setupLabelText()
setupControlsInStackView()
}
fileprivate func setupLabelText() {
for num in 0...(dataModel.count - 1) {
controlArray[num].titleLabel.text = dataModel[num]
}
}
// let stackView = UIStackView(frame: .zero) I have tried to declare the stackView here but it doesn't fix my issue.
func setupControlsInStackView() {
var stackViewArray = [SetupViewControl]()
for num in 0...(dataModel.count - 1) {
controlArray[num].isUserInteractionEnabled = true
controlArray[num].addTarget(self, action: #selector(goalViewControlTapped(_:)), for: .touchUpInside)
stackViewArray.append(controlArray[num])
}
let stackView = UIStackView(arrangedSubviews: stackViewArray)
stackView.alignment = .fill
stackView.distribution = .fillEqually
stackView.axis = .horizontal
stackView.translatesAutoresizingMaskIntoConstraints = false
addSubview(stackView)
stackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 8).isActive = true
stackView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -8).isActive = true
stackView.topAnchor.constraint(equalTo: topAnchor, constant: 15).isActive = true
addSubview(selectionLine)
selectionLine.backgroundColor = .white
selectionLine.translatesAutoresizingMaskIntoConstraints = false
selectionLine.heightAnchor.constraint(equalToConstant: 1).isActive = true
selectionLine.topAnchor.constraint(equalTo: stackView.bottomAnchor).isActive = true
selectionLine.widthAnchor.constraint(equalToConstant: 50).isActive = true
selectionLineCenterX = selectionLine.centerXAnchor.constraint(equalTo: leadingAnchor, constant: -100)
selectionLineCenterX.isActive = true
}
#objc fileprivate func goalViewControlTapped(_ sender: SetupViewControl) {
print("This is not getting printed!!!")
selectionLineCenterX.isActive = false
selectionLineCenterX = selectionLine.centerXAnchor.constraint(equalTo: sender.centerXAnchor)
selectionLineCenterX.isActive = true
UIView.animate(withDuration: 0.25, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0.5, options: .curveEaseIn, animations: {
self.layoutIfNeeded()
}, completion: nil)
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
let testView = SetupView(frame: .zero, color: UIColor.blue)
view.addSubview(testView)
testView.translatesAutoresizingMaskIntoConstraints = false
testView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
testView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
testView.heightAnchor.constraint(equalToConstant: 100).isActive = true
testView.widthAnchor.constraint(equalToConstant: 365).isActive = true
}
}
// For live view in playground
let vc = ViewController()
vc.preferredContentSize = CGSize(width: 375, height: 812)
PlaygroundPage.current.liveView = vc
Thanks for reading my question.
Does your UIStackView show as having an ambiguous layout when you open the view debugger? If so, that may be causing the internal views to not receive the touch events.
You can provide UIStackView with either:
x and y constraints only
or
x, y, width and height.
In the above case the height constraint is missing.

Resources