the below code is the viewController that is navigated with a navigationItem navigationItem.leftBarButtonItem = UIBarButtonItem(title: from a previous tableViewController and I am trying to produce a UIView in my viewController. However nothing is showing.
import UIKit
class SecondpgController: UIViewController {
var inputContainerView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor .gray
let inputContainerView = UIView()
self.view.addSubview(inputContainerView)
//inputContainerView.backgroundColor = UIColor(red: 162/255, green: 20/255, blue: 35/255, alpha: 1)
inputContainerView.backgroundColor = .white
inputContainerView.translatesAutoresizingMaskIntoConstraints = false
//inputContainerView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 300).isActive = true
//nputContainerView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 10).isActive = true
inputContainerView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor, constant: 200).isActive = true
inputContainerView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor, constant: 200).isActive = true
The app is running well however after reaching the view controller, Nothing is shown but only a grey screen.
Why is this happening and how can I solve it?
Your problem is that you constraints are only setting x and y position for the UIView you are creating. You are missing width and height.
Try this constraints:
inputContainerView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
inputContainerView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
inputContainerView.widthAnchor.constraint(equalToConstant: 100).isActive = true
inputContainerView.heightAnchor.constraint(equalToConstant: 100).isActive = true
This code means that your UIView will be centred vertically and horizontally in your self.view and also it has a width and height of 100. It will look like this:
Hope it helps. Happy Coding
You have added constraints to place inputContainerView to the centre of the screen but did not add constraints for it's height and width. Adding the following code might solve your issue:
inputContainerView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor, constant: 0).isActive = true
inputContainerView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor, constant: 0).isActive = true
inputContainerView.addConstraint(NSLayoutConstraint(item: inputContainerView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 200))
inputContainerView.addConstraint(NSLayoutConstraint(item: inputContainerView, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 200))
Check this: https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/AutolayoutPG/ProgrammaticallyCreatingConstraints.html
Ensure that the constants for CenterXAnchor and CenterYAnchor are 0, so the view aligns at the centre. And make sure you add inputContainerView only once either as an outlet or programmatically.
Related
I want to add a view in my view controller programmatically and centralise it. I added the view as subview to the parent view and enable autolayout yet its not showing.
import UIKit
class ViewController: UIViewController {
lazy var newView:UIView = {
let view = UIView()
view.backgroundColor = #colorLiteral(red: 0.4745098054, green: 0.8392156959, blue: 0.9764705896, alpha: 1)
view.frame = CGRect(x: 0, y: 0, width: 200, height: 200)
return view
}()
let titleLable = UILabel()
let bodyLabel = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(newView)
newView.translatesAutoresizingMaskIntoConstraints = false
newView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
newView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
}
}
Try this way
NSLayoutConstraint(item: newView,
attribute: NSLayoutConstraint.Attribute.centerX,
relatedBy: NSLayoutConstraint.Relation.equal,
toItem: view,
attribute: NSLayoutConstraint.Attribute.centerX,
multiplier: 1,
constant: 0).isActive = true
NSLayoutConstraint(item: newView,
attribute: NSLayoutConstraint.Attribute.centerY,
relatedBy: NSLayoutConstraint.Relation.equal,
toItem: view,
attribute: NSLayoutConstraint.Attribute.centerY,
multiplier: 1,
constant: 0).isActive = true
Size constraints are missing for newView. You removed them with newView.translatesAutoresizingMaskIntoConstraints = false. To restore all required constraints add the lines below to viewDidLoad:
newView.widthAnchor.constraint(equalToConstant: 200).isActive = true
newView.heightAnchor.constraint(equalToConstant: 200).isActive = true
here is the problem...
first, you set the frame of newView,
second, you also set translatesAutoresizingMaskIntoConstraints = false
so Xcode does not understand whats you want to set frame or constraints.
so if you set frame then you cannot add constraints again on it later.
so the best solution is here according to your need is:
view.addSubview(newView)
newView.translatesAutoresizingMaskIntoConstraints = false
newView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
newView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
newView.widthAnchor.constraint(equalToConstant: 200).isActive = true
newView.heightAnchor.constraint(equalToConstant: 200).isActive = true
I want to put two buttons with images on left and right edges of the screen, and insert a UITextField between them. In storyboard everything is fine, but I need to do it programmatically.
Source:
class SecondViewController: UIViewController {
override func loadView() {
super.loadView()
self.view.backgroundColor = .white
let leftButton = UIButton()
leftButton.setImage(UIImage(named: "first"), for: .normal)
leftButton.setTitle("", for: .normal)
let rightButton = UIButton()
rightButton.setImage(UIImage(named: "second"), for: .normal)
rightButton.setTitle("", for: .normal)
let textField = UITextField()
textField.placeholder = "clear"
textField.borderStyle = .roundedRect
textField.contentHorizontalAlignment = .left
textField.contentVerticalAlignment = .center
let stackView = UIStackView()
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.alignment = .fill
stackView.distribution = .fill
stackView.axis = .horizontal
stackView.spacing = 15
stackView.addArrangedSubview(leftButton)
stackView.addArrangedSubview(textField)
stackView.addArrangedSubview(rightButton)
self.view.addSubview(stackView)
NSLayoutConstraint(item: stackView, attribute: .leading, relatedBy: .equal, toItem: self.view, attribute: .leading, multiplier: 1.0, constant: 15).isActive = true
NSLayoutConstraint(item: stackView, attribute: .trailing, relatedBy: .equal, toItem: self.view, attribute: .trailing, multiplier: 1.0, constant: -15).isActive = true
NSLayoutConstraint(item: stackView, attribute: .top, relatedBy: .equal, toItem: self.view, attribute: .top, multiplier: 1.0, constant: 50).isActive = true
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
I need a result like on first image.
But at result, I have second.
What did I do wrong ?
You have an elementary constraint ambiguity. You could easily have discovered this just by switching to the View Debugger; you would see three exclamation marks warning you of the problem. The layout engine does not magically know which of the three views should be allowed to stretch horizontally. You have to tell it:
textField.setContentHuggingPriority(UILayoutPriority(249), for: .horizontal)
Set constraints like
NSLayoutConstraint.activate([
stackView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 50),
stackView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 15),
stackView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -15),
stackView.heightAnchor.constraint(equalToConstant: 45),
leftButton.widthAnchor.constraint(equalToConstant: 30),
rightButton.widthAnchor.constraint(equalToConstant: 30),
])
Another small change
rightButton.imageView?.contentMode = .scaleAspectFit
leftButton.imageView?.contentMode = .scaleAspectFit
Result
I have the following UIView, how can text be added in the center of this UIView programmatically?
This is the UIView code:
let newView = UIView()
newView.backgroundColor = .groupTableViewBackground
self.view.addSubview(newView)
newView.translatesAutoresizingMaskIntoConstraints = false
if #available(iOS 11.0, *) {
let guide = self.view.safeAreaLayoutGuide
newView.trailingAnchor.constraint(equalTo: guide.trailingAnchor).isActive = true
newView.leadingAnchor.constraint(equalTo: guide.leadingAnchor).isActive = true
newView.topAnchor.constraint(equalTo: guide.topAnchor).isActive = true
newView.heightAnchor.constraint(equalToConstant: 50).isActive = true
} else {
NSLayoutConstraint(item: newView,
attribute: .top,
relatedBy: .equal,
toItem: view, attribute: .top,
multiplier: 1.0, constant: 0).isActive = true
NSLayoutConstraint(item: newView,
attribute: .leading,
relatedBy: .equal, toItem: view,
attribute: .leading,
multiplier: 1.0,
constant: 0).isActive = true
NSLayoutConstraint(item: newView, attribute: .trailing,
relatedBy: .equal,
toItem: view,
attribute: .trailing,
multiplier: 1.0,
constant: 0).isActive = true
newView.heightAnchor.constraint(equalToConstant: 50).isActive = true
}
This was my attempt at adding text to the center of the UIView programmatically, but I'm not sure why it is not working?
let lb = UILabel()
lb.centerXAnchor.constraint(equalTo: newView.centerXAnchor).isActive = true
lb.centerYAnchor.constraint(equalTo: newView.centerYAnchor).isActive = true
lb.text="anything"
newView.backgroundColor = UIColor.white
// show on screen
self.view.addSubview(newView)
newView.addSubview(lb)
lb.center = newView.center
UPDATE:
How can this button border below the UIView that's under the navigation controller be added?
When it comes to adding constraints to the view programmatically, note that you have to set translatesAutoresizingMaskIntoConstraints to false (but I get the feeling that you already know this, and just forgot to add it to the label)
let lb = UILabel()
lb.textAlignment = .center
lb.numberOfLines = 0
newView.addSubview(lb)
lb.translatesAutoresizingMaskIntoConstraints = false
lb.centerXAnchor.constraint(equalTo: newView.centerXAnchor).isActive = true
lb.centerYAnchor.constraint(equalTo: newView.centerYAnchor).isActive = true
Add border (assuming you want to add the border to the newView):
let border = UIView()
newView.addSubview(border)
border.translatesAutoresizingMaskIntoConstraints = false
border.leadingAnchor.constraint(equalTo: newView.leadingAnchor).isActive = true
border.trailingAnchor.constraint(equalTo: newView.trailingAnchor).isActive = true
border.bottomAnchor.constraint(equalTo: newView.bottomAnchor).isActive = true
border.heightAnchor.constraint(equalToConstant: 1).isActive = true
But for the border it would probably be cleaner to write an extension on UIView, so the code can be reusable in other places, if you ever need it again
I would like to put a UIView above all other views. I saw that this is possible using the UIScreen object. However, it looks like the UIScreen doesn't have a Safe Area. This let's the View overlap with the Statusbar.
How can I place a View above all other Views while still using the Safe Area Insets?
I'm using this code in the Appdelegate's DidFinishLaunchingWithOptions():
window?.makeKeyAndVisible()
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = UIColor.red
window?.addSubview(view)
window?.bringSubview(toFront: view)
let heightConstraint = NSLayoutConstraint(item: view, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 44)
view.addConstraint(heightConstraint)
let layoutGuide = window!.safeAreaLayoutGuide
let layoutGuideConstraints = [
view.topAnchor.constraint(equalTo: layoutGuide.topAnchor, constant: 8),
view.leadingAnchor.constraint(equalTo: layoutGuide.leadingAnchor, constant: 8),
view.trailingAnchor.constraint(equalTo: layoutGuide.trailingAnchor, constant: -8)
]
NSLayoutConstraint.activate(layoutGuideConstraints)
I am attempting to get a UIView courseView to autolayout. I would like to have the proportions of the UIView remain and fill up until the outermost edges are 15 point from the edge of the superview.
For some reason courseView fills the entire superview (minus the 15 points) and does not resize to fit. So some of it does not show and is cut off.
self.view.addSubview(courseView!)
let aspectConstraint = NSLayoutConstraint(item: courseView,
attribute: .Height,
relatedBy: .Equal,
toItem: courseView,
attribute: .Width,
multiplier: courseView.frame.size.height / courseView.frame.size.width,
constant: 0.0)
aspectConstraint.active = true
let topConstraint = courseView.topAnchor.constraintGreaterThanOrEqualToAnchor(topLayoutGuide.bottomAnchor, constant: 15)
topConstraint.active = true
let leadingConstraint = courseView.leadingAnchor.constraintLessThanOrEqualToAnchor(view.leadingAnchor, constant: 15)
leadingConstraint.active = true
let trailingConstraint = courseView.trailingAnchor.constraintGreaterThanOrEqualToAnchor(view.trailingAnchor, constant: -15)
trailingConstraint.active = true
let bottomConstraint = courseView.bottomAnchor.constraintLessThanOrEqualToAnchor(view.bottomAnchor, constant: -15)
bottomConstraint.active = true
Any ideas? Thanks!
Just disable translatesAutoresizingMaskIntoConstraints before adding the constraints and it should work just fine.
courseView.translatesAutoresizingMaskIntoConstraints = false;
And by the way, you do not need the aspectConstraint because that will most probably break the constratints (it did for me, when I tried).