How to update the constant height constraint of a UIView programmatically? - swift

I have a UIView and I set the constraints using Xcode Interface Builder.
Now I need to update that UIView instance's height constant programmatically.
There is a function that goes like myUIView.updateConstraints(), but I don't know how to use it.

Select the height constraint from the Interface builder and take an outlet of it. So, when you want to change the height of the view you can use the below code.
yourHeightConstraintOutlet.constant = someValue
yourView.layoutIfNeeded()
Method updateConstraints() is an instance method of UIView. It is helpful when you are setting the constraints programmatically. It updates constraints for the view. For more detail click here.

If you have a view with multiple constrains, a much easier way without having to create multiple outlets would be:
In interface builder, give each constraint you wish to modify an identifier:
Then in code you can modify multiple constraints like so:
for constraint in self.view.constraints {
if constraint.identifier == "myConstraint" {
constraint.constant = 50
}
}
myView.layoutIfNeeded()
You can give multiple constrains the same identifier thus allowing you to group together constrains and modify all at once.

Change HeightConstraint and WidthConstraint Without creating IBOutlet.
Note: Assign height or width constraint in Storyboard or XIB file. after fetching this Constraint using this extension.
You can use this extension to fetch a height and width Constraint:
extension UIView {
var heightConstraint: NSLayoutConstraint? {
get {
return constraints.first(where: {
$0.firstAttribute == .height && $0.relation == .equal
})
}
set { setNeedsLayout() }
}
var widthConstraint: NSLayoutConstraint? {
get {
return constraints.first(where: {
$0.firstAttribute == .width && $0.relation == .equal
})
}
set { setNeedsLayout() }
}
}
You can use:
yourView.heightConstraint?.constant = newValue

Drag the constraint into your VC as an IBOutlet. Then you can change its associated value (and other properties; check the documentation):
#IBOutlet myConstraint : NSLayoutConstraint!
#IBOutlet myView : UIView!
func updateConstraints() {
// You should handle UI updates on the main queue, whenever possible
DispatchQueue.main.async {
self.myConstraint.constant = 10
self.myView.layoutIfNeeded()
}
}

You can update your constraint with a smooth animation if you want, see the chunk of code below:
heightOrWidthConstraint.constant = 100
UIView.animate(withDuration: animateTime, animations:{
self.view.layoutIfNeeded()
})

To update a layout constraint you only need to update the constant property and call layoutIfNeeded after.
myConstraint.constant = newValue
myView.layoutIfNeeded()

If the above method does not work then make sure you update it in Dispatch.main.async{} block. You do not need to call layoutIfNeeded() method then.

First connect the Height constraint in to our viewcontroller for creating IBOutlet like the below code shown
#IBOutlet weak var select_dateHeight: NSLayoutConstraint!
then put the below code in view did load or inside any actions
self.select_dateHeight.constant = 0 // we can change the height value
if it is inside a button click
#IBAction func Feedback_button(_ sender: Any) {
self.select_dateHeight.constant = 0
}

Create an IBOutlet of NSLayoutConstraint of yourView and update the constant value accordingly the condition specifies.
//Connect them from Interface
#IBOutlet viewHeight: NSLayoutConstraint!
#IBOutlet view: UIView!
private func updateViewHeight(height:Int){
guard let aView = view, aViewHeight = viewHeight else{
return
}
aViewHeight.constant = height
aView.layoutIfNeeded()
}

If you update your constraints with animation then add layout subview in UIView.animate...
for example,
#IBOutlet viewHeight: NSLayoutConstraint!
#IBOutlet view: UIView!
private func updateViewHeight(height:Int){
guard let aView = view, aViewHeight = viewHeight else{
return
}
aViewHeight.constant = height
UIView.animateWithDuration(0.5, delay: 0) { [self] in
aView.layoutIfNeeded()
}
}

Related

Changing constraints by pressing a button

Is there a way to change view’s centerXAnchor constraint to another object (with animation) by pressing a button while the app is running?
Thank's for all of the answers!
First, you need to create an IBOutlet for your constraint from the storyboard, something similar to this.
#IBOutlet weak var centerXConstraint: NSLayoutConstraint!
And when the button is pressed, you should change the constraint value and update the view layout.
centerXConstraint.constant = setYourValueHere
UIView.animate(withDuration: 0.3, animations: {
self.view.layoutIfNeeded()
})
If you want to add constraints programmatically, then remove #IBOutlet weak.
var centerXConstraint: NSLayoutConstraint!
Assign your view's center X anchor to it.
centerXConstraint = yourView.centerXAnchor.constraint(equalTo: super.view.centerXAnchor, constant: 0)
centerXConstraint.isActive = true
after that, you can change it as described above.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var centerXConstraintOutlet: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func buttonClickAction(_ sender: UIButton) {
animateViewCenterXConstraint()
}
func animateViewCenterXConstraint() {
UIView.animate(withDuration: 0.3) {
self.centerXConstraintOutlet.constant = 30
self.view.layoutIfNeeded()
}
}
}
1) Create view’s centerXAnchor constraints related to both the objects.
2) Take outlets of both the constraints.
3) Activate and de-activate them on click of the button as you wish.
Declare variable for centerXAnchor constraint and assign value on button action. You can try this:
var constraintOfCenterXAnchor: NSLayoutConstraint = NSLayoutConstraint()
in viewDidLoad() set constraintOfCenterXAnchor.constant = 0
When button pressed, change constraint value and update view
constraintOfCenterXAnchor.constant = 30
UIView.animate(withDuration: 0.3, animations: {
self.view.layoutIfNeeded()
})

ScrollView Constraint problem threw storyboard

So I maybe successfully created a scroll view following a tutorial but something is terribly wrong. So I'm trying to create a scroll view with a table view inside and some buttons and labels and everything works fine but as soon as I add a single constraint it all goes just white with no explanation. I would assume content view is messing things up but I'm not sure, thx in advance!
So following some other people problems I tried filling constraints programmatically and doing views and subviews programmatically aswell, keep in mind tho that rest of constraints I did on storyboard. Btw I have tried equal width and height on newView --> scroll view and nothing seems to change.
my view hierarchy looks like this
myViewController -> View -> scrollView -> newView
class ThirdViewController: UIViewController {
#IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
scrollView.addSubview(newView)
newView.leftAnchor.constraint(equalTo: scrollView.leftAnchor).isActive = true
newView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
newView.rightAnchor.constraint(equalTo: scrollView.rightAnchor).isActive = true
newView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
//tableView1.dataSource = self
//tableView1.delegate = self
//tableView1.register(UITableViewCell.self, forCellReuseIdentifier: "cell1")
}
#IBOutlet weak var newView: UIView!
override func viewWillLayoutSubviews() {
scrollView.contentSize = CGSize(width: 375, height: 1950)
}
}
Sorry, if question is layout pretty badly - I'm not that pro!

Dynamically adding to NSStackView and Adding Scrolling Functionality

Like the title says, I am trying to dynamically add NSTextViews and NSImageViews to a NSStackView. First, I added a Scroll View using IB and that made a hierarchy of Bordered Scroll View -> Clip View -> Main View -> Stack View (Vertical). I want to be able to dynamically add views to the stack view and be able to scroll through them all. I used autolayout on the Bordered Scroll View.
The problem: I tested this by adding 100 NSTextViews and incrementing their y-positions to stack up on each other. But, I cannot scroll to the top. I have been trying to understand this for a couple days but I just cannot figure it out. I cannot scroll and see all the text views, but when I increase the window size I can see more of them. TIA! `
import Cocoa
class ViewController: NSViewController {
var xLoc = CGFloat(0)
var yLoc = CGFloat(0)
#IBOutlet weak var mainView: NSStackView!
#IBOutlet weak var belowMainView: NSStackView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
for index in 1...100 {
var txt = "Num: \(index)"
setup(text: txt)
}
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
func setup(text: String){
let tempTextView = NSTextView(frame: NSMakeRect(xLoc, yLoc, 320, 10))
tempTextView.append(text)
tempTextView.isEditable = false
tempTextView.translatesAutoresizingMaskIntoConstraints = false
// mainView.addSubview(tempTextView)
belowMainView.addSubview(tempTextView)
yLoc += 20
}
}
// Adding an append function to textView functionality
extension NSTextView {
func append(_ string: String) {
self.textStorage?.append(NSAttributedString(string: string))
// Scrolls to end of document if it is out of view
self.scrollToEndOfDocument(nil)
}
}`

(swift) update a number to label will make the view get back to original position

demo image
When I update a number to label will make the view get back to original position.
class ViewController: UIViewController {
#IBOutlet weak var label: UILabel!
#IBOutlet var aview: UIView!
var number = 0
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func plus(sender: UIButton) {
number++
label.text = "number:\(number)"
}
#IBAction func move(sender: AnyObject) {
aview.frame.origin.y -= 20
}
}
I couldn't find the answer on web, please help me to fix this problem.Thank you very much!
Because your xib or Storyboard you set use Autolayout:
So if you don't set constrain system will auto generate it. When you change frame by set frame it effect but when you access to it. It will auto back to old position.
if you don't want it happen. You set in viewDidLoad:
self.view.translatesAutoresizingMaskIntoConstraints = false
Issue is probably related to a constraint reloading when the label reloads.
Instead of setting aview.frame.origin.y -= 20 you should make an outlet to the constraint holding the y position of your aView and then update the constant of that constraint outlet instead.

2 UIView.size.height don't work?

There is 2 UIView control.
#IBOutlet weak var vw: UIView!;
#IBOutlet weak var lbl: UILabel!;
I want to set height = 0.0;
Like this...
vw.frame.size.height = 0.0;
lbl.frame.size.height = 0.0;
And
I do this !
override func viewWillAppear( animated: Bool )
{
vw.frame.size.height = 0.0;
lbl.frame.size.height = 0.0;
}
override func viewDidAppear( animated: Bool )
{
vw.frame.size.height = 0.0;
lbl.frame.size.height = 0.0;
}
But It's don't work !!!
How can I solved the problem ?
Why don't work ? Is script ?
It's very different to MicroSoft Control.
Thanks in advance ^^;;;
Assuming your code isn't crashing because the vw object is nil. Then its probably a problem with auto layout.
You have them as #IBOutlets, are the views created in a storyboard?
If so, are you using auto layout? If you are, you need to set the constant of the constraint for their height. Create an outlet to the constraint and connect it in storyboard to it (the same way you did the views).
#IBOutlet weak var viewHeightConstraint: NSLayoutConstraint?
override func viewWillAppear( animated: Bool ) {
vwHeightConstraint.constant = 0
}
Your constraints still exist, so even when you set the frame height, the auto layout constraint just sets it back to the height defined in the storyboard.