I was trying to center the text in the middle of a view, but instead, received an error. Here's my code as a reference.
let textbox = UITextField()
textbox.text = "Hello"
textbox.sizeToFit()
textbox.centerXAnchor.constraint(equalTo: textboxView.centerXAnchor).isActive = true
textbox.centerYAnchor.constraint(equalTo: textboxView.centerYAnchor).isActive = true
textbox.delegate = self
self.textboxView.addSubview(textbox)
You cannot constraint a view relative to another view unless they are first related.
You need to add the subview first before setting the constraints
let textbox = UITextField()
textbox.text = "Hello"
textbox.translatesAutoresizingMaskIntoConstraints = false
self.textboxView.addSubview(textbox)
textbox.centerXAnchor.constraint(equalTo: textboxView.centerXAnchor).isActive = true
textbox.centerYAnchor.constraint(equalTo: textboxView.centerYAnchor).isActive = true
textbox.delegate = self
You haven’t given lot of detail surrounding the rest of your view controller, so you may have already added it somewhere else.
However, when using autolayout constraints you must turn off auto masking.
textbox.translatesAutoresizingMaskIntoConstraints = false
You should also add the textbox as a subview prior to setting constraints.
Related
I am trying to display a basic UITextView programmatically. The problem is, if I want to display a UILabel with the same constraints and settings, it's all fine, I can have it displayed. However, if I change it to a UITextView, it just disappears. I created an empty project, just to check it, but still, no avail, just does not display.
Here's my code that works fine for a UILabel:
view = UIView()
view.backgroundColor = .systemBackground
explanationView = UILabel()
explanationView.layer.zPosition = 1
explanationView.translatesAutoresizingMaskIntoConstraints = false
explanationView.numberOfLines = 10
view.addSubview(explanationView)
NSLayoutConstraint.activate([
explanationView.centerXAnchor.constraint(equalTo: view.layoutMarginsGuide.centerXAnchor),
explanationView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor),
explanationView.trailingAnchor.constraint(equalTo: view.layoutMarginsGuide.trailingAnchor),
explanationView.bottomAnchor.constraint(greaterThanOrEqualTo: view.layoutMarginsGuide.bottomAnchor, constant: -20)
])
I am using layer.zPosition to display it over a UIImageView. I also add .isScrollEnabled for the text view. I also tried creating the UITextView via a computed property, but did not have any luck either.
Any help is appreciated.
Edit: Below is the code that I use for the text view.
explanationView = UITextView()
explanationView.layer.zPosition = 1
explanationView.translatesAutoresizingMaskIntoConstraints = false
explanationView.isScrollEnabled = true
view.addSubview(explanationView)
I'm trying to add a simple NSView with a checkbox as an accessory view to an NSOpenPanel, but when I run my program, I get an error saying The Open/Save panel was supplied an accessory view with bad layout constraints, resulting in a view that is zero [height/width]. Here are the constraints I've added to the view:
And here are the constraints for the checkbox:
Here's the code for creating the NSOpenPanel:
let dlgOpenSounds: NSOpenPanel = NSOpenPanel()
let optionsView = BatchAddOptionsView()
dlgOpenSounds.accessoryView = optionsView
dlgOpenSounds.accessoryView?.awakeFromNib()
let result = dlgOpenSounds.runModal()
if result == .OK {
// do stuff
}
Anyone know what I'm doing wrong?
I ran into the same issue with a similar arrangement created in code, and finally worked it out. My implementation is handled in a custom NSView subclass, which I then add as the NSOpenPanel's .accessoryView from the view controller where I display the panel.
private func setup() {
hiddenFilesCheckbox = NSButton(checkboxWithTitle: "Show Hidden Files", target: self, action: #selector(hiddenFilesCheckboxValueChanged))
guard let checkbox = hiddenFilesCheckbox else {
os_log("Hidden files checkbox is nil")
return
}
addSubview(checkbox)
checkbox.translatesAutoresizingMaskIntoConstraints = false
checkbox.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 12).isActive = true
checkbox.topAnchor.constraint(equalTo: self.topAnchor, constant: 12).isActive = true
self.heightAnchor.constraint(greaterThanOrEqualToConstant: frame.height).isActive = true
self.widthAnchor.constraint(greaterThanOrEqualToConstant: frame.width).isActive = true
}
"hiddenFilesCheckbox" is declared as a property of my custom NSView subclass. I played around with some other hard-coded values for the constants, but these worked best in my tests. I pass in the openPanel to the subclass's initializer to use its frame to set the accessoryView's width. I used a hard-code value of 40 for the height in the initializer that isn't included here. After setting up the accessory view with these constraints, the warnings stopped appearing and the accessory view appears as desired/expected.
Try setting up the view like this (Xcode 10.1). First make sure that AutoLayout on the view is not selected. Then:
Change the view width and height to whatever is appropriate (I'm using a 'small' control size)
Setup the checkbox similar to:
Again, adjust the width and height as necessary. No other constraints should be added.
Note that if you save and reuse the accessory view in multiple panel.beginModalSheet() calls, you'll get a console warning because the previous beginModalSheet() added layout constraints.
I have a UIViewController that has some base controls and in the center has a UIView (as container of swappable ui controls). I swap out the UI controls in this center UIView (container) depending on what the user is trying to do. All of the UI controls that go in to the UIView container are defined programmatically and I use programatic constraints to place them inside the UIView container.
This works fine for all of the sets of UI controls I have done so far. Now I am adding a set of controls to the UIView container that includes a UITableView
I cant figure out how to get the TableView to show up inside the UIView programatically. I can define say a button and label and run the app and see the container with the button and the label. If I add the UITableView as below then the container just does not show up at all.
// tableView
tableView.leftAnchor.constraint(equalTo: inputsContainerView.leftAnchor).isActive = true
tableView.bottomAnchor.constraint(equalTo: inputsContainerView.bottomAnchor).isActive = true
tableView.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor).isActive = true
tableView.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor, multiplier: 1/2).isActive = true
prior to the above code I have already added all of the needed controls to the container subview ...
// Add controls to the view
inputsContainerView.addSubview(listTextView)
inputsContainerView.addSubview(listImageButton)
inputsContainerView.addSubview(listImageClear)
inputsContainerView.addSubview(tableView)
If I leave off the tableview then the container shows up with the other three fields. If I add the tableview then the container and all the other three controls are gone.
How do I add the tableView to the UIView and have it show up?
Here is how I defined the UITable view
let tableView: UITableView = {
let tv = UITableView()
return tv
}()
as a compare, when I define others controls like this they show up fine after adding to the subview and setting the constraints programatically
e.g.
// DEFINE
let listTextView: UITextView = {
let textView = UITextView()
textView.translatesAutoresizingMaskIntoConstraints = false
textView.text = ""
textView.textColor = defaultTextColor
textView.font = subtitleFont
textView.layer.borderColor = UIColor.black.cgColor
textView.layer.borderWidth = 1
textView.textAlignment = NSTextAlignment.left
return textView
}()
then later
// Place - with constraints
// listTextView
listTextView.leftAnchor.constraint(equalTo: inputsContainerView.leftAnchor, constant: padFromLeft).isActive = true
listTextView.topAnchor.constraint(equalTo: inputsContainerView.topAnchor, constant: 10).isActive = true
listTextView.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor, multiplier: 9/16).isActive = true
listTextView.heightAnchor.constraint(equalTo: inputsContainerView.widthAnchor, multiplier: 5/16).isActive = true
Just added my comment as detailed answer, so others can see the solution faster and benefit from it.
So taken from the apple documentation, to set your own constraints programmatically, you need to set translatesAutoresizingMaskIntoConstraints to false:
Note that the autoresizing mask constraints fully specify the view’s size and position; therefore, you cannot add additional constraints to modify this size or position without introducing conflicts. If you want to use Auto Layout to dynamically calculate the size and position of your view, you must set this property to false, and then provide a non ambiguous, nonconflicting set of constraints for the view.
So in your case you miss to set it for your table view, when you define it. Just add this line to it:
tv.translatesAutoresizingMaskIntoConstraints = false
Currently, I set the height and width constraints of one of my views that I later add to the stack view as follows: (For your information, productsTable is a UITableView.)
productsTable.heightAnchor.constraintEqualToConstant(tableHeight).active = true
productsTable.widthAnchor.constraintEqualToConstant(stackWidth).active = true
stackView.insertArrangedSubview(productsTable, atIndex: productsTableIndex)
Later, in ViewWillAppear, I want to change the productsTable height as follows:
productsTable.heightAnchor.constraintEqualToConstant(newHeight).active = true.
Despite this, the table view remains the same size after (changing/updating) the constraint in ViewWillAppear. Is there anything I am doing wrong or can do differently to achieve the desired effect?
You need to keep a reference to the height constraint that you create the first time.
let heightConstraint = productsTable.heightAnchor.constraintEqualToConstant(tableHeight)
heightConstraint.active = true
Later, in viewWillAppear() you'll be able to directly set the constant attribute of this constraint to newHeight.
heightConstraint.constant = newHeight
I have a label with a single character that I wish to be bigger than the UIView that it's a subview of. However, I need to hide the overflowing parts of the character.
For an example, this is the result I'm trying to achieve:
Where the character/Icon is the tags in lighter green in the background
Like the above example I'm using the font called "fontawesome" and their icon set. However in Swift I havn't been able to find any options to hide the overflowing parts.
Here's the current code:
var actionBox = UIView()
var actionLabel = UILabel()
var actionIcon = UILabel()
// #actionBox
actionBox.translatesAutoresizingMaskIntoConstraints = false
actionBox.backgroundColor = UIColor.formulaGreenColor()
cellView.addSubview(actionBox)
actionIcon.translatesAutoresizingMaskIntoConstraints = false
actionIcon.font = UIFont(name: "fontawesome", size: 80)
actionIcon.text = ""
actionIcon.textColor = UIColor.colorWithHex("#13E6A7")
actionBox.addSubview(actionIcon)
I know I can technically make another 2 UIViews, with a background color, and layer those on top. But that's not exactly an elegant solution.
So how can I hide the rest of the label, that's overflowing it's superView?
Any help would be greatly appreciated!
You are searching for clipsToBounds property:
view.clipsToBounds = true
Where view is your container view.