I need to set the layout of a ScrollView full-screen with autolayout. at the moment I have this code but not the full-height sect and I can not understand which variable to change. I have this code
func setControlsType(controlsType: ControlsType, bounds: CGRect, startingDim: CGFloat, scrolledDim: CGFloat) {
self.controlsType = controlsType
if Utils.isInPortraitState() {
/*self.startingFrame = CGRect(x: 0, y: bounds.height - startingDim, width: bounds.width, height: scrolledDim)
self.scrolledFrame = CGRect(x: 0, y: bounds.origin.y + bounds.height - scrolledDim, width: bounds.width, height: scrolledDim)*/
self.startingFrame = CGRect(x: 0, y: bounds.height, width: bounds.width, height: scrolledDim)
self.scrolledFrame = CGRect(x: 0, y: bounds.origin.y + bounds.height, width: bounds.width, height: scrolledDim)
} else {
self.startingFrame = CGRect(x: startingDim - scrolledDim, y: 0, width: scrolledDim, height: bounds.height)
self.scrolledFrame = CGRect(x: 0, y: 0, width: scrolledDim, height: bounds.height)
}
func setControls(type: ControlsType) {
let safeBounds = SafeAreaManager.letsDoIt(view: self, upon: .bounds)
/*let sDim = (Utils.isInPortraitState() ? safeBounds.height + (self.workbenchView.frame.origin.y + self.workbenchView.frame.size.height) : safeBounds.width + (self.workbenchView.frame.size.width + self.workbenchView.frame.width))*/
let sDim = CGFloat(0)
var scDim = CGFloat(0)
if Utils.isIPad() {
if Utils.isInPortraitState() {
scDim = safeBounds.height - (self.workbenchView.frame.origin.y + 2 * (self.workbenchView.frame.size.height/3))
} else {
scDim = self.workbenchView.frame.origin.x + self.workbenchView.frame.size.width/3
}
} else {
if Utils.isInPortraitState() {
scDim = safeBounds.height - self.workbenchView.frame.size.height
} else {
scDim = safeBounds.width - self.workbenchView.frame.size.width
}
}
self.controlsView.setControlsType(controlsType: type, bounds: safeBounds, startingDim: sDim, scrolledDim: scDim)
}
It seems that this code is not in your view controller so I see two options among others:
You pass your view and your scroll view to one of your function in the file that you shared above. Then you apply contraints to your scroll view so its frame match your view frame. This function will look like this:
func resizeScrollView(view: UIView, scrollView: UIScrollView) {
NSLayoutConstraint(item: scrollView, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: scrollView, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: scrollView, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: scrollView, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1, constant: 0).isActive = true
}
Or you can access the bounds property of the screen of your device via UIScreen and in this case the function will look like this:
func resizeScrollView(scrollView: UIScrollView) {
scrollView.bounds = UIScreen.main.bounds
}
Then you'll have to set the position of your scroll view in your view controller.
Related
I have a reusable view class, with the function .addDisapearingView() when added to another view displays the text in the functions parameters. Both the label and its container view are programmatically created. When there's long text in the label, I want the label, and the view to both grow in height. When there's text too long for the label, the label doesn't grow-and the text, subsequently, doesn't clip/go to next line. I'm trying to get the container view to expand programmatically based upon the text.
I've tried an extension that detects when the label is truncated. Using that extension, I used the += operator on the label and view to expand both of them with no luck.
while label.isTruncated {
print("printing while truncating in the while loop")
regView.frame.size.height += 5
label.frame.size.height += 5
}
The interesting thing with that is, I've used that code before, with the addition of adding 5 to the height constraint of the view in the storyboard to expand the size of the label for text, and it worked. That lead me to believe that my problem might reside somewhere in editing the height constraint for the regView.
I've tried countless variations of
label.adjustsFontSizeToFitWidth = true
label.numberOfLines = 3
label.lineBreakMode = .byWordWrapping
label.translatesAutoresizingMaskIntoConstraints = false
label.frame.size.height = regView.frame.size.height
label.sizeToFit()
regView.layoutSubviews()
I've tried changing the frame of the view and label, changing the constaints at the top of the code, and the answers from other questions.
Code:
Truncated Label Extension:
extension UILabel {
var isTruncated: Bool {
guard let labelText = text else {
return false
}
let labelTextSize = (labelText as NSString).boundingRect(
with: CGSize(width: frame.size.width, height: .greatestFiniteMagnitude),
options: .usesLineFragmentOrigin,
attributes: [.font: font],
context: nil).size
return labelTextSize.height > bounds.size.height
}
}
View constraint changer:
extension UIView {
func updateConstraint(attribute: NSLayoutAttribute, constant: CGFloat) -> Void {
if let constraint = (self.constraints.filter{$0.firstAttribute == attribute}.first) {
constraint.constant = constant
self.layoutIfNeeded()
}
}
}
Whole function:
func addDisapearingView(toview: UIView, text: String, textColor: UIColor, colorView: UIColor, alpha: CGFloat, height: CGFloat){
regView.backgroundColor = colorView
regView.alpha = alpha
regView.frame = CGRect(x: toview.bounds.minX, y: toview.bounds.minY, width: toview.frame.size.width, height: height)
toview.addSubview(regView)
regView.translatesAutoresizingMaskIntoConstraints = false
if #available(iOS 11.0, *) {
let guide = toview.safeAreaLayoutGuide
regView.trailingAnchor.constraint(equalTo: guide.trailingAnchor).isActive = true
regView.leadingAnchor.constraint(equalTo: guide.leadingAnchor).isActive = true
regView.topAnchor.constraint(equalTo: guide.topAnchor).isActive = true
regView.heightAnchor.constraint(equalToConstant: height).isActive = true
} else {
NSLayoutConstraint(item: regView,
attribute: .top,
relatedBy: .equal,
toItem: toview, attribute: .top,
multiplier: 1.0, constant: 0).isActive = true
NSLayoutConstraint(item: regView,
attribute: .leading,
relatedBy: .equal, toItem: toview,
attribute: .leading,
multiplier: 1.0,
constant: 0).isActive = true
NSLayoutConstraint(item: regView, attribute: .trailing,
relatedBy: .equal,
toItem: toview,
attribute: .trailing,
multiplier: 1.0,
constant: 0).isActive = true
NSLayoutConstraint(item: regView, attribute: NSLayoutAttribute.height, relatedBy: .equal, toItem: toview, attribute: .height, multiplier: 1.0, constant: height).isActive = true
//regView.heightAnchor.constraint(equalToConstant: height).isActive = true
}
let label = UILabel(frame: CGRect(x: regView.frame.origin.x, y: regView.frame.origin.y, width: regView.frame.width, height: height))
label.text = text
label.font = UIFont(name: "Arial", size: 12)
label.textColor = textColor
label.adjustsFontSizeToFitWidth = true
label.numberOfLines = 3
label.lineBreakMode = .byWordWrapping
label.translatesAutoresizingMaskIntoConstraints = false
label.frame.size.height = regView.frame.size.height
label.sizeToFit()
regView.layoutSubviews()
regView.addSubview(label)
print("Label Height: \(label.frame.height)")
print("Reg view height: \(regView.frame.height)")
while label.isTruncated {
print("label is truncated")
regView.frame.size.height += 5
label.frame.size.height += 5
label.updateConstraint(attribute: NSLayoutAttribute.height, constant: regView.frame.height)
label.updateConstraint(attribute: NSLayoutAttribute.width, constant: regView.frame.width)
regView.layoutSubviews()
label.sizeToFit()
print("Label Height: \(label.frame.height)")
print("Reg view height: \(regView.frame.height)")
}
//remove
Timer.scheduledTimer(withTimeInterval: 2.8, repeats: false) { (action) in
UIView.animate(withDuration: 2.8, animations: {
self.regView.removeFromSuperview()
label.removeFromSuperview()
})
}
}
which is called by: ReusableView().addDisapearingView(toview: self.view, text: "Anonymous posts will still show up in your profile page!, more text text to test in teh view that doen't work!", textColor: UIColor.white, colorView: UIColor.darkGray, alpha: 0.9, height: 20)
The interesting thing(That I tried to fix) was that even if the height is set to 40, or a value where two lines of text could fit, the label still doesn't expand/truncate, much less if the height param is 20.
Any help would be greatly appreciated!
I guess you completely need auto-layout and make regView expand according to the label's text without any height constraints
let regView = UIView()
func addDisapearingView(toview: UIView, text: String, textColor: UIColor, colorView: UIColor, alpha: CGFloat, height: CGFloat){
regView.backgroundColor = colorView
regView.alpha = alpha
toview.addSubview(regView)
regView.translatesAutoresizingMaskIntoConstraints = false
if #available(iOS 11.0, *) {
let guide = toview.safeAreaLayoutGuide
NSLayoutConstraint.activate([
regView.trailingAnchor.constraint(equalTo: guide.trailingAnchor),
regView.leadingAnchor.constraint(equalTo: guide.leadingAnchor),
regView.topAnchor.constraint(equalTo: guide.topAnchor),
// regView.bottomAnchor.constraint(equalTo: guide.bottomAnchor).isActive = true
// regView.heightAnchor.constraint(equalToConstant: height).isActive = true
])
} else {
NSLayoutConstraint(item: regView,
attribute: .top,
relatedBy: .equal,
toItem: toview, attribute: .top,
multiplier: 1.0, constant: 0).isActive = true
NSLayoutConstraint(item: regView,
attribute: .leading,
relatedBy: .equal, toItem: toview,
attribute: .leading,
multiplier: 1.0,
constant: 0).isActive = true
NSLayoutConstraint(item: regView, attribute: .trailing,
relatedBy: .equal,
toItem: toview,
attribute: .trailing,
multiplier: 1.0,
constant: 0).isActive = true
// NSLayoutConstraint(item: regView, attribute: NSLayoutConstraint.Attribute.height, relatedBy: .equal, toItem: toview, attribute: .height, multiplier: 1.0, constant: height).isActive = true
//regView.heightAnchor.constraint(equalToConstant: height).isActive = true
}
let label = UILabel()
label.text = text
label.font = UIFont(name: "Arial", size: 12)
label.textColor = textColor
label.numberOfLines = 3
label.lineBreakMode = .byWordWrapping
label.translatesAutoresizingMaskIntoConstraints = false
regView.addSubview(label)
NSLayoutConstraint.activate([
label.trailingAnchor.constraint(equalTo: regView.trailingAnchor),
label.leadingAnchor.constraint(equalTo: regView.leadingAnchor),
label.topAnchor.constraint(equalTo: regView.topAnchor),
label.bottomAnchor.constraint(equalTo: regView.bottomAnchor) // this is the key behind expanding
])
Timer.scheduledTimer(withTimeInterval:3, repeats: false) { (action) in
UIView.animate(withDuration: 2.8, animations: {
self.regView.removeFromSuperview()
})
}
}
Edit:
let regView = UIView()
func addDisapearingView(toview: UIView, text: String, textColor: UIColor, colorView: UIColor, alpha: CGFloat, height: CGFloat){
regView.backgroundColor = colorView
regView.alpha = alpha
toview.addSubview(regView)
regView.translatesAutoresizingMaskIntoConstraints = false
var topCon:NSLayoutConstraint!
if #available(iOS 11.0, *) {
let guide = toview.safeAreaLayoutGuide
topCon = regView.bottomAnchor.constraint(equalTo: guide.topAnchor)
topCon.isActive = true
NSLayoutConstraint.activate([
regView.trailingAnchor.constraint(equalTo: guide.trailingAnchor),
regView.leadingAnchor.constraint(equalTo: guide.leadingAnchor),
// regView.bottomAnchor.constraint(equalTo: guide.bottomAnchor).isActive = true
// regView.heightAnchor.constraint(equalToConstant: height).isActive = true
])
} else {
topCon = NSLayoutConstraint(item: regView,
attribute: .bottom,
relatedBy: .equal,
toItem: toview, attribute: .top,
multiplier: 1.0, constant: 0)
topCon.isActive = true
NSLayoutConstraint(item: regView,
attribute: .leading,
relatedBy: .equal, toItem: toview,
attribute: .leading,
multiplier: 1.0,
constant: 0).isActive = true
NSLayoutConstraint(item: regView, attribute: .trailing,
relatedBy: .equal,
toItem: toview,
attribute: .trailing,
multiplier: 1.0,
constant: 0).isActive = true
// NSLayoutConstraint(item: regView, attribute: NSLayoutConstraint.Attribute.height, relatedBy: .equal, toItem: toview, attribute: .height, multiplier: 1.0, constant: height).isActive = true
//regView.heightAnchor.constraint(equalToConstant: height).isActive = true
}
let label = UILabel()
label.text = text
label.font = UIFont(name: "Arial", size: 12)
label.textColor = textColor
label.numberOfLines = 3
label.lineBreakMode = .byWordWrapping
label.translatesAutoresizingMaskIntoConstraints = false
regView.addSubview(label)
NSLayoutConstraint.activate([
label.trailingAnchor.constraint(equalTo: regView.trailingAnchor),
label.leadingAnchor.constraint(equalTo: regView.leadingAnchor),
label.topAnchor.constraint(equalTo: regView.topAnchor),
label.bottomAnchor.constraint(equalTo: regView.bottomAnchor) // this is the key behind expanding
])
regView.layoutIfNeeded()
topCon.constant += self.regView.frame.height
UIView.animate(withDuration: 2) {
toview.layoutIfNeeded()
}
Timer.scheduledTimer(withTimeInterval:3, repeats: false) { (action) in
UIView.animate(withDuration: 2.8, animations: {
self.regView.removeFromSuperview()
})
}
}
I have SQLite database file and UILabel, and I set text for label from database on the number of characters after convert String to Characters, and I added extension its name (length), its job counts the number of characters.
My problem in this picture is : The UILabels are not organized in sizes and positions in per devices I want them to have their positions in the center of X-Axis
Questions:
1) How to set the label into center and set spaces right and left of screen for labels (per device) ??
2) How to set width for labels if device is iPhone 7/6S/6 plus width = 50, if device is iPhone 7/6S/6 width = 45 and if device is iPhone SE/5S/5C/5 width = 38 ??
3) Finally, how does the label become smaller by 10 if the number of characters is more than 8 ?
This my code :
func createTarget(id: Int) {
listdata = dbHelpr.getDatabase(rowId: id)
for data in listdata {
let lengthOfChar : CGFloat = data.ans.length
let yAxis : CGFloat = (self.view.frame.height) * 60%
let width: CGFloat = view.frame.size.width - 40 // frame width
var targetWidth: CGFloat = (width - (lengthOfChar - 1) * 5) / lengthOfChar
let targetHeigt : CGFloat = 5
if lengthOfChar >= 8 {
targetWidth = 40
} else {
targetWidth = 50
}
let totalWidth: CGFloat = (targetWidth * lengthOfChar) + ((lengthOfChar - 5) * 5)
for (indexTar, tar) in data.ans.characters.enumerated() {
let x : CGFloat = (width / 2) - (totalWidth / 2)
let xx : CGFloat = (CGFloat(indexTar) * targetWidth) + (CGFloat(indexTar) * 5) + 20
var xAxis : CGFloat = (x + xx)
xAxis = width - xAxis
let targetLabel = UILabel(frame: CGRect(x: xAxis, y: yAxis, width: targetWidth, height: targetHeigt))
targetLabel.backgroundColor = .white
targetLabel.layer.masksToBounds = true
targetLabel.layer.cornerRadius = 5
targetLabel.text = String(describing: tar)
targetLabel.textAlignment = .center
targetLabel.textColor = .white
self.view.addSubview(targetLabel)
}
}
}
In order to position your labels you need a few things things:
Label container to keep everything centered and with margins from the screen sides
Constraints between your labels depending on the device sizes etc..
If you need to break lines - you need to handle it manually as well
To identify device kinds and have different logics, you can check this posts:
iOS: How to determine the current iPhone/device model in Swift?
In order to fill your view with labels, here is a sample code to achieve this:
self.view.backgroundColor = UIColor.black
let labelContainerView : UIView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: 10))
labelContainerView.translatesAutoresizingMaskIntoConstraints = false
let containerLeftConstraint : NSLayoutConstraint = NSLayoutConstraint(item: self.view, attribute: .left, relatedBy: .greaterThanOrEqual, toItem: labelContainerView, attribute: .left, multiplier: 1, constant: 8)
let containerRightConstraint : NSLayoutConstraint = NSLayoutConstraint(item: self.view, attribute: .right, relatedBy: .greaterThanOrEqual, toItem: labelContainerView, attribute: .right, multiplier: 1, constant: 8)
let containerCenterX : NSLayoutConstraint = NSLayoutConstraint(item: labelContainerView, attribute: .centerX, relatedBy: .equal, toItem: self.view, attribute: .centerX, multiplier: 1, constant: 0)
let containerCenterY : NSLayoutConstraint = NSLayoutConstraint(item: labelContainerView, attribute: .centerY, relatedBy: .equal, toItem: self.view, attribute: .centerY, multiplier: 1, constant: 0)
self.view.addSubview(labelContainerView)
self.view.addConstraints([ containerLeftConstraint, containerRightConstraint, containerCenterX, containerCenterY ])
// Add some labels
let totalLabels : Int = 10
var lastAddedLabel : UILabel? = nil
for labelAt : Int in 1 ... totalLabels
{
var addedConstraint : [NSLayoutConstraint] = [NSLayoutConstraint]()
let label : UILabel = UILabel(frame: CGRect.zero)
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "_"
label.textColor = UIColor.white
label.textAlignment = .center
label.adjustsFontSizeToFitWidth = true
if (lastAddedLabel != nil)
{
// Add left constraint to previous label
let leftConstraint : NSLayoutConstraint = NSLayoutConstraint(item: label, attribute: .left, relatedBy: .equal, toItem: lastAddedLabel!, attribute: .right, multiplier: 1, constant: 8)
let equalWidth : NSLayoutConstraint = NSLayoutConstraint(item: label, attribute: .width, relatedBy: .equal, toItem: lastAddedLabel!, attribute: .width, multiplier: 1, constant: 0)
addedConstraint.append(contentsOf: [ leftConstraint, equalWidth ])
}
else
{
// Add left constraint to super view
let leftConstraint : NSLayoutConstraint = NSLayoutConstraint(item: labelContainerView, attribute: .left, relatedBy: .equal, toItem: label, attribute: .left, multiplier: 1, constant: 0)
addedConstraint.append(leftConstraint)
}
// Add top bottom constraint
let topConstraint : NSLayoutConstraint = NSLayoutConstraint(item: labelContainerView, attribute: .top, relatedBy: .equal, toItem: label, attribute: .top, multiplier: 1, constant: 0)
let bottomConstraint : NSLayoutConstraint = NSLayoutConstraint(item: labelContainerView, attribute: .bottom, relatedBy: .equal, toItem: label, attribute: .bottom, multiplier: 1, constant: 0)
addedConstraint.append(contentsOf: [ topConstraint, bottomConstraint ])
// Add right constraint if this is the last label
if (labelAt == totalLabels)
{
let rightConstraint : NSLayoutConstraint = NSLayoutConstraint(item: labelContainerView, attribute: .right, relatedBy: .equal, toItem: label, attribute: .right, multiplier: 1, constant: 0)
addedConstraint.append(rightConstraint)
}
labelContainerView.addSubview(label)
labelContainerView.addConstraints(addedConstraint)
lastAddedLabel = label
}
self.view.layoutIfNeeded()
This gives out the output:
Changes you might need to make:
Change the "totalLabels" number depending on your requirement
Maybe adding another width constraint to the first generated label in order to define a specific with for all labels - the rest of the labels keep the same width as the first
Adjust the containing view margins from both sides for different devices
Handle new lines manually by pre-calculating the width the labels might use.
Good luck
I solved my problem and this answer :
func createTarget(id: Int) {
listdata = dbHelpr.getDatabase(rowId: id)
var targetHeigt = CGFloat()
let viewWidth = self.view.frame.size.width
if viewWidth == 320 {
targetHeigt = 2.5
} else {
targetHeigt = 5
}
for data in listdata {
let yAxis : CGFloat = (self.view.frame.height) * 60%
let i = data.ans.length
// char count
let width: Int = Int(view.frame.size.width) - 40
// frame width
var targetWidth: Int = (width - (i - 1) * 5) / i
if targetWidth > 50 {
targetWidth = 50
}
let totalWidth: Int = (targetWidth * i) + ((i - 1) * 5)
for x in 0..<i {
let currentWidth: Int = (width / 2) - (totalWidth / 2) + (x * targetWidth) + (x * 5) + 20
let targetLabel = UILabel(frame: CGRect(x: CGFloat(currentWidth), y: yAxis, width: CGFloat(targetWidth), height: targetHeigt))
targetLabel.backgroundColor = .white
targetLabel.layer.masksToBounds = true
targetLabel.layer.cornerRadius = 5
targetLabel.textAlignment = .center
targetLabel.textColor = .white
for i in listdata {
let tar = data.ans.characters.map{String($0)}
targetLabel.text = String(describing: tar)
}
self.view.addSubview(targetLabel)
}
}
}
I have in app: TextView and TableView. I create their in code. And now I need to make programming autolayout. But I don't know how it make. Please help.
P.S. Sorry for my English =)
let displayWidth: CGFloat = self.view.frame.width
let displayHeight: CGFloat = self.view.frame.height
myTextView = UITextView(frame: CGRect(x: 0, y: 20, width: displayWidth, height: displayHeight / 3))
creatTextView()
myTableView = UITableView(frame: CGRect(x: 0, y: displayHeight / 3, width: displayWidth, height: displayHeight * 2 / 3))
createTable()
A quick AutoLayout guide
Documentation: https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/AutolayoutPG/
I usually set up constraints to the left, right, bottom/top and width/height constraints. That can be achieved in multiple ways.
Some keywords:
Leading: Means the left part of the object
Trailing: Means the right part of an object
First you want to make all the necessary variables to hold your autolayout guides and for the view you are using autolayout on you'll need to set translatesAutoresizingMaskIntoConstraints to false like this:
self.btn.translatesAutoresizingMaskIntoConstraints = false
var btnLeading: NSLayoutConstraint!
var btnBottom: NSLayoutConstraint!
var btnTop: NSLayoutConstraint!
var btnWidth: NSLayoutConstraint!
I just copied some code I used in a project, but I think you'll get the hang of it eventually. self.userLocationBtn is just a button in my view I want to position in a UIView I have subclassed.
self.btnLeading = NSLayoutConstraint(
item: self.userLocationBtn,
attribute: .leading,
relatedBy: .equal,
toItem: self,
attribute: .leading,
multiplier: 1.0,
constant: 5.0)
self.btnBottom = NSLayoutConstraint(
item: self.userLocationBtn,
attribute: .bottom,
relatedBy: .equal,
toItem: self,
attribute: .bottom,
multiplier: 1.0,
constant: 0.0)
self.btnTop = NSLayoutConstraint(
item: self.userLocationBtn,
attribute: .top,
relatedBy: .equal,
toItem: self,
attribute: .top,
multiplier: 1.0,
constant: 0.0)
self.btnWidth = NSLayoutConstraint(
item: self.userLocationBtn,
attribute: .width,
relatedBy: .equal,
toItem: self,
attribute: .height,
multiplier: 1.0,
constant: 0.0)
self.addSubview(self.doneButton)
After the view is added we need to activate the constraints and then update the view.
NSLayoutConstraint.activate([self.btnLeading, self.btnBottom, self.btnTop, self.btnWidth])
self.view.layoutIfNeeded() //Lays out the subviews immediately.
I want to add a subview with some constraints.
But my view do not appear.
Below is some code, does anyone know what is going wrong?
(If i add a UITextField e.g. it works fine...)
class TestViewController:UIViewController {
override func viewDidLoad() {
//Do not work...
addAndLayout(v: UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 0)))
//Works fine
//addAndLayout(v: UITextField(frame: CGRect(x: 0, y: 0, width: 0, height: 0)))
}
func addAndLayout(v:UIView) {
v.backgroundColor = UIColor.red
view.addSubview(v)
v.translatesAutoresizingMaskIntoConstraints = false
let leading = NSLayoutConstraint(item: v, attribute: .leading, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: .leading, multiplier: 1, constant: 0)
let trailing = NSLayoutConstraint(item: v, attribute: .trailing, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: .trailing, multiplier: 1, constant: 0)
let top = NSLayoutConstraint(item: v, attribute: .top, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: .top, multiplier: 1, constant: 0)
view.addConstraints([leading, trailing, top])
}
}
Add a height constraint or bottom constraint and you should see the view. The reason it works with UITextField is that UITextField has an intrinsic content size while UIView does not.
I'm using LineChartView from Charts in an osx app and I add it as follows to my view:
let lineChartView = LineChartView(frame: NSRect(x: 0, y: 0, width: 300, height: 200))
let ys1 = Array(1..<10).map { x in return sin(Double(x) / 2.0 / 3.141 * 1.5) }
let ys2 = Array(1..<10).map { x in return cos(Double(x) / 2.0 / 3.141) }
let yse1 = ys1.enumerate().map { x, y in return ChartDataEntry(x: Double(x), y: y) }
let yse2 = ys2.enumerate().map { x, y in return ChartDataEntry(x: Double(x), y: y) }
let data = LineChartData()
let ds1 = LineChartDataSet(values: yse1, label: "Hello")
ds1.colors = [NSUIColor.redColor()]
data.addDataSet(ds1)
let ds2 = LineChartDataSet(values: yse2, label: "World")
ds2.colors = [NSUIColor.blueColor()]
data.addDataSet(ds2)
lineChartView.data = data
lineChartView.gridBackgroundColor = NSUIColor.whiteColor()
lineChartView.descriptionText = "Linechart Demo"
lineChartView.animate(xAxisDuration: 2.0, yAxisDuration: 2.0, easingOption: .Linear)
lineChartView.translatesAutoresizingMaskIntoConstraints = true
self.view.addSubview(lineChartView)
let horizontalConstraint = NSLayoutConstraint(item: inspectorView, attribute: NSLayoutAttribute.Left, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.Left, multiplier: 1, constant: 20)
self.view.addConstraint(horizontalConstraint)
let verticalConstraint = NSLayoutConstraint(item: inspectorView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.GreaterThanOrEqual, toItem: titleLabel, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 10)
self.view.addConstraint(verticalConstraint)
self.view.addConstraint(NSLayoutConstraint(item: inspectorView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.GreaterThanOrEqual, toItem: self.view, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 10))
Whenever lineChartView.translatesAutoresizingMaskIntoConstraints is false the chart is not drawn. If I set it to true the chart is drawn but the runtime says it could not satisfy all constraints.
I also do the same with a standard NSButton for which .translatesAutoresizingMaskIntoConstraints = false works as expected
Why isn't it working for LineChartView and what needs to be changed?
UPDATE: as was pointed out in the comments: Adding height and width constraints solved the problem