I have the following view with the following constraints:
#IBOutlet weak var square1ViewOutlet: UIView!
Which is inserted inside the following view using the storyboard:
#IBOutlet weak var holderView: UIView!
My problem is that I am not being able to override the positioning of square1ViewOutlet established by the storyboard. The following code does not have any effect. I've tried some variations as bellow, but nothing works and the view is really stuck to previous storyboard constraints. I am calling this with my viewDidLoad method.
square1ViewOutlet.frame.origin.y = self.holderView.frame.origin.y + 20
square1ViewOutlet.frame.origin.x = self.holderView.frame.origin.x + 20
square1ViewOutlet.frame = CGRectOffset(CGRect(origin: square1ViewOutlet.frame.origin, size: square1ViewOutlet.frame.size), 20, 20)
square1ViewOutlet.center = CGPointMake(150, 150)
square1ViewOutlet.frame = CGRectMake( 100, 200, square1ViewOutlet.frame.size.width, square1ViewOutlet.frame.size.height )
Any idea what am I doing wrong here?
When you use autolayout and you try to change frame dimensions or positions like your code, instead to correct the correct constraints involved, you can disable you constraints effect causing warnings and unexpected view dimensions and movements.
The correct way to do it is to link the constraints as IBOutlets in your code:
#IBOutlet weak var customViewTopConstraint: NSLayoutConstraint
#IBOutlet weak var customViewHeightConstraint: NSLayoutConstraint
#IBOutlet weak var customViewLeadingConstraint: NSLayoutConstraint
#IBOutlet weak var customViewWidthConstraint: NSLayoutConstraint
And work with these properties changing it's constant value (.constant).
These rules are valid for all the code where you have to change frame dimensions, so check all your code and change it to a constraints work.
Can you please try that code inside your viewDidAppear() method. please go to the link below iOS UIViewController Lifecycle.
Since you have placed your code inside viewDidLoad method, that may be the reason your frames are not applied.
If this not worked please try layoutIfNeeded method for your view after the frames are set. layoutIfNeeded forces the receiver to layout its subviews immediately if required.
By this way you can set your frames for your views. But doing this way will alter your constraints that you had set in your xib file. If you really want to change your view frames, then best way will be create outlet for your constraints and change the values for that constraints. Hope this will help :)
Related
I am following ios11-app-development-bootcamp by Angela. I am having problem to update width of a UIView. Here is the code I am using
#IBOutlet var progressBar: UIView!
progressBar.frame.size.width = (view.frame.size.width / 13) * CGFloat(questionNumber + 1)
The width is setting correctly but the UI is not updating. I have searched and found below solution.
#IBOutlet weak var progressBarWidthConstraint: NSLayoutConstraint!
progressBarWidthConstraint.constant = (view.frame.size.width / 13) * CGFloat(questionNumber + 1)
Why is below code working and above code not working. I am watching this lecture link
Thanks in advance.
In viewDidload it will take an initial width of the view given in the storyboard.
we can set the width in viewDidAppear
or
Add view.setNeedsLayout() Or view.layoutIfNeeded() in viewDidLoad after setting the width.
If you want to redraw your view, you just need to call layoutIfNeeded
Use this method to force the view to update its layout immediately. When using Auto Layout, the layout engine updates the position of views as needed to satisfy changes in constraints. Using the view that receives the message as the root view, this method lays out the view subtree starting at the root. If no layout updates are pending, this method exits without modifying the layout or calling any layout-related callbacks.
I am trying to create a UIView in a library project and use it in my application. I have added auto layout constraints as follows:
But it produces the following result:
The labels have numOfLines as 0 but still, empty labels are displaying empty space.
I have only given the height of the white view in the center (56px)
Edit:
I am using the view from library as following:
One solution with Storyboard, where UILabel heights are dynamic based on its's text,
Or,
you can try using NSLayoutConstraint for the UILabel hights, for the ones you want to hide when the value is not there for the label,
#IBOutlet weak var errorLabelHeight: NSLayoutConstraint!
then,
if errorLabel.text.isEmpty {
errorLabelHeight.isActive = true
errorLabelHeight.constant = 0
} else {
errorLabelHeight.active = false
//works as usual
}
view.layoutIfNeeded()
I want to set the height of my UITextView programmatically to fit the contents accordingly. I've set the UITextView's default height to follow layout constraints I've set, but wish to change it when the user touches a button.
#IBOutlet weak var descriptionHeight: NSLayoutConstraint!
I've tried to use layoutIfNeeded(), but it doesn't change the size of my text view (as the size is kept by the layout constraint).
I've tried to temporarily disable the constraints like so:
print("before: \(descriptionTextView.frame)")
descriptionHeight.active = false
descriptionTextView.layoutIfNeeded()
print("after: \(descriptionTextView.frame)")
descriptionHeight.constant = descriptionTextView.frame.height
descriptionHeight.active = true
But when when accessing the outlet after deactivating it, it throws an exception:
fatal error: unexpectedly found nil while unwrapping an Optional value
It seems that it is calculating the size properly though:
before: (8.0, 8.0, 398.0, 100.0)
after: (8.0, 8.0, 398.0, 954.666666666667)
Why does this happen?
Is there a better way of calculating and setting the proper size of my UITextView?
Make the outlet strong:
#IBOutlet strong var descriptionHeight: NSLayoutConstraint!
Edit:
It seems like the latest version of Xcode adds the outlets as:
#IBOutlet var descriptionHeight: NSLayoutConstraint!
as #Dan mentioned in the comments.
I have a circle in the centre of a screen with a margin constraint of 50 on either end. Hence, the width of the circle is dependent on the screen size.
So, what I tried was this:
Approach 1
I set up the margins in the storyboard to define the circle width (50 on left and right)
Then I used the following code:
#IBOutlet weak var helpButHeight: NSLayoutConstraint!
#IBOutlet weak var helpBut: UIButton!
ViewDidLoad:
helpButHeight.constant = helpBut.frame.size.width
This didn't work.
Since the screen width is 400, and the margin is 50 on either end, then helpBut.frame.size.width should have given me 300.
Instead it gave me 46.
Approach 2
This was my work-around:
ViewDidLoad:
let screenSize: CGRect = UIScreen.mainScreen().bounds
helpButHeight.constant = screenSize.width - 100
because 100 = 50 + 50, the two margins.
Works fine !
Question
Why did I have to do this? Why did the first approach not work? Why 46 and not 300?
The reason is that constraints haven't kicked in, in the viewDidLoad function. The lifecycle looks something like
viewDidLoad -- Constraints haven't set
viewWillAppear -- Constraints haven't set
viewWillLayoutSubviews -- Constraints are setting
viewDidLayoutSubviews -- Constraints are set
viewDidAppear -- Constraints are set
If you want any view to be in center just put the horizontal/vertical center constraint...No code required.. If you want to have padding just put the left and right constraints...Just to remind you don't use both of them together...It'll break...
I am trying to change the position of a label in my viewDidAppear() method using the following code:
self.StartTextLabel.text = self.starttext
self.StartTextLabel.center.x = ChangeStart.center.x
The text in the label changes just find but the labels position does not change.
I have tried doing this with and without the code being within
dispatch_async(dispatch_get_mail_queue()){
}
The label was originally build in the IntefaceBuilder and is linked to my controller via
#IBOutlet weak var StartTextLabel: UILabel!
Does anyone have any idea why the label is not moving?
Thanks