Extra constraints are logged when I NSLog myBtn.constraints - ios

I have a button inside a view. I have set image for my button in interface builder.
The constraints that I have added to my button in interface builder is:
Right space to superview = 10
top space to superview = 10
bottom space to superview >= 10
left space to a label >= 10
All thing work fine and I have no problem with my layout.
But when I log the button constraints with this code:
NSLog(#"constraints for btnBack is: %#", self.btnBack.constraints);
the console logs:
constraints for btnBack is:(
"<NSContentSizeLayoutConstraint:0x7c35c400 H:[UIButton:0x7c3588a0(102)] Hug:250 CompressionResistance:750>"
"<NSContentSizeLayoutConstraint:0x7c35c450 V:[UIButton:0x7c3588a0(92)] Hug:250 CompressionResistance:750>")
I know that the top and left and right and bottom constraints shouldn't log here because they are the superview constraints not the button constrains.
But here I didn't add any width and height constrains to my button(even in code).
Why constraints height and width are logged in the console?

If a view has a natural width based on its content, it returns that width as intrinsicContentSize.width. Otherwise, it sets intrinsicContentSize.width to UIViewNoIntrinsicMetric.
Similarly, if it has a natural height, it returns that width as intrinsicContentSize.height. Otherwise, it sets intrinsicContentSize.height to UIViewNoIntrinsicMetric.
A button has a natural size (both width and height), determined by its title, font, image, and maybe other details. So its intrinsicContentSize.width and intrinsicContentSize.height are both valid sizes, not UIViewNoIntrinsicMetric.
When intrinsicContentSize.width != UIViewNoIntrinsicMetric, auto layout installs a special constraint of type NSContentSizeLayoutConstraint on the view. Similarly, when intrinsicContentSize.height != UIViewNoIntrinsicMetric, auto layout installs an NSContentSizeLayoutConstraint on the view.
For the details of what these special constraints do, see this answer.

If view.translatesAutoresizingMaskIntoConstraints is FALSE then UIKit may add NSContentSizeLayoutConstraint to the view. In that case auto-layout uses -sizeThatFits: or intrinsicContentSize to compute the view's size.
If you have a view that you are moving from one superview to another, be sure to reset view.translatesAutoresizingMaskIntoConstraints. If the new superview uses auto-layout, set translatesAutoresizingMaskIntoConstraints to FALSE. If the new superview does not use auto-layout, set to TRUE. If you fail to reset translatesAutoresizingMaskIntoConstraints then you may see unexpected frame animations.

Related

How to corrently use UIViews systemLayoutSizeFitting to get the height to show all subviews using a given width?

TD;DR
It seems that in some cases systemLayoutSizeFitting does not return the correct height to correctly show / position all subviews of a view. Am I using systemLayoutSizeFitting wrong or is there some other way to avoid this?
Long story:
The XIB file of a UIViewController does not only contain the main view but also a number of other views which are added to the view controllers view at runtime. All these additional views should get the same height when they are added to the view controllers view.
The views might look like this: A simple container view holding some subviews which are stacked on top of each other.
Since the height of the container view should be flexible, the vertical spacing between the bottom button and the lable above it, uses a grater-than constraint.
To give all views the same height, I tried to measure the necessary height of each view using systemLayoutSizeFitting:
#IBOutlet var pageViews: [UIView]!
override func viewDidLoad() {
super.viewDidLoad()
var maxHeight: CGFloat = 0
for pageView in pageViews {
// Add pageView somewhere on view and give it leading, trailing and top
// constraint, but no height constraint yet.
addToView(pageView)
maxHeight = max(maxHeight, pageView.systemLayoutSizeFitting(CGSize(width: view.frame.width, height: UIView.layoutFittingCompressedSize.height), withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel).height)
}
for pageView in pageViews {
// Give all pageViews the same height
pageView.heightAnchor.constraint(equalToConstant: maxHeight).isActive = true
}
}
This does not work, when the label text becomes to long:
In the right example the height is not large enough and thus the button is squeezed. I can counter act this by raising the vertical compression resistance of the button, however in this case the other controls (e.g. the title label) is squeezed...
Why is this? Why does not systemLayoutSizeFitting return a height which is sufficent to show all controls without any squeezing?
Its actually smash button's height when label text is getting bigger . You are setting top and bottom constraints but button height is not declared so when label getting bigger , view basically say "I can reduce button height before updating my height , I have space.Bottom and top constraints are still same , didn't effect."
Giving the constant height constraints of button might be fix your issue.
If you want your view to resist to compression you should use the defaultHigh priority as a verticalFittingPriority instead of fittingSizeLevel.

How to resize the superview to conform to the subviews constraints

I created a custom UIView class where I create 2 UILabels and 1 UIImageView. I set the constraints for each element. Since the Labels will hold dynamic text each view will have a different height. How can I resize the height of the view? the constraints (top to bottom) are:
View Top > 16 > Label1 > 8 > ImageView > 8 > Label2 > 16 > View Bottom
The problem is: I have to initialize the UIView with a frame. and no matter what I try the view always uses the height of the frame given by initializing. And I cannot calculate the height of all elements and set a new frame because the labels habe sometimes 1 and sometimes 5 lines.
This is how the view looks at runtime
This is how its supposed to look like
Thanks in advance
You have to initialize the view with a frame, but when setting translatesAutoresizingMaskIntoConstraints to false after initializing, the frame passed in becomes irrelevant. Therefore, you can do what #BallpointBen recommended in the comments and pass in .zero:
let newCustomView = CustomView(frame: .zero)
newCustomView.translatesAutoresizingMaskIntoConstraints = false
// auto layout constraints should now determine height

Label doesn't show all the text inside scrollView

I want the DecriptionLabel (the Lorem Ipsum one) to have all the text inside it visible. As you can see, it is getting trimmed.
The two buttons should be under everything else, but in the case where DescriptionLabel contains a small text, the buttons should stick to the bottom of the view.
This is why I chose a >= 20 distance between the buttons and DescriptionLabel if it makes any sense.
How can I solve the trimming of the text?
Thanks.
I was originally answering How to make button stick to bottom of scroll view if the content isn't large enough? but since it is marked as duplicate of this one I am posting my answer here. Please try to set your constraints the following way: https://imageshack.com/a/img923/6671/Txzu98.png
The trick is that you set Button.Bottom Equal To ContainerView.Bottom with lower priority (I use 750) than Button.Top Greater Than Or Equal To Label.Bottom (Here I use default 1000)
The Label has to have number of lines set to 0. The height of the button should be set by height constraint (in this case is 50). The Container View Height constraint should be with low priority (in this case 250)
You should run the code to see actual result on device or simulator. Storyboard shows it a bit differently. For the current question:
https://imageshack.com/a/img923/7276/tQeT0h.png The basic idea is the same. Button Down has the same constraints as Button from above answer without Button.Top Greater Than Or Equal To Label.Bottom. There should be fixed vertical constraint between Button Up and Button Down. I am setting Button Up with fixed Height and setting trailing and leading constraint equal to trailing and leading of Button Down. The constraint Button.Top Greater Than Or Equal To Label.Bottom is now Button Up.Top Greater Than Or Equal To Label.Bottom
Have you set numberOfLines for label to 0 (that means autosize the label according to its text length)?
You should add the following constraints:
(following in sudo code)
// Constraints for ScrollView
scrollView.top = ViewController.view.top
scrollView.leading = ViewController.view.leading
scrollView.trailing = ViewController.view.trailing
scrollView.bottom = ViewController.view.bottom
// Constraints for View
view.top = scrollView.top
view.leading = scrollView.leading
view.trailing = scrollView.trailing
view.bottom = scrollView.bottom
// Width of view
view.width = ViewController.view.width
Now you just need to make sure you have layout constraints for each child of the 'view' and it's height will be correct and display the full size of the textview.
Add the following constraint:
scrollview.contentview.height >= safearea.height
This may show an error in interface builder but works in my tests:
To remove the design time error you could set a design time intrinsic content size for the scrollview's contentview (in my case I used the safe area's height of 554):
Another option (without placeholder values in IB) is to create the following constraint...
scrollview.contentview.height = safearea.height
... and change its priority to a value lower than the label's vertical content compression resistancy.

Swift: Views not adjusting to programmatic constraints

I have a view that I am making hidden at the bottom of the screen, and want the scrollView above it to adjust and fill the void space.
The view at the bottom of the screen is a GADBannerView and has a fixed height of 50 (bannerHeight). The scroll view above it has a constraint to the bottom of the container that equals 50 (scrollConstraint). See photo.
In viewDidLoad is am setting these constraints to the following:
bannerHeight.constant = 0
scrollConstraint.constant = 0
This is causing the bannerView did disappear but the scroll view is staying in it's original position and not filling the void space.
You can force the superview to take into account the change of the constraint because this does not happen automatically. Add your code to viewDidLayoutSubviews() instead or simply call view.layoutIfNeeded() after you set the constants to 0 in the viewDidLoad().
If this does not work, you can try this alternative approach:
Go to your Storyboard and click on the scroll view's bottom constraint (the blue line that gives the scroll view its bottom constraint of 50). In the Attributes Inspector you should be able to see details about your constraint, it should look something like this
In the field that asks for an Identifier, give it the name "ScrollViewBottom" or whatever name you like.
Now loop over all the constraints that make up your scroll view and use the identifier name to find the correct one and change it's constant as follows
for constraint in yourScrollView.superview!.constraints {
if constraint.identifier == "ScrollViewBottom" {
constraint.constant = 0
}
}
Finally, force the view to take into account of this change by calling the following straight after
view.layoutIfNeeded()

Which Constraint we need to make dynamic View height in iOS

As I am new to iOS. So forgive me if it is duplicate or very basic question.
I am taking one View. Approx below is the size .
x : 5 y : 5
Width : 590 Height : 100
and I set constraint it
Top to superView 5
Trailing to superView 5
Leading to superView 5
Now I have one Label which have dynamic Text and the Text is too large.
And the Label Constraint is below
Top to superView 5
Trailing to superView 5
Leading to superView 5
and when i set the background color of the View the color is not set. If the Text is to Long. So how to set the Height of the View and also set background so that it looks clear.
Code :
public override void ViewDidLoad()
{
base.ViewDidLoad();
lbl_one.Text = "This is a long label which have long text inside the writing. This is a long label which have long text inside the writing. This is a long label which have long text inside the writing. This is a long label which have long text inside the writing";
lbl_one.LineBreakMode = UILineBreakMode.WordWrap;
lbl_one.Lines = 0;
view_main.BackgroundColor = UIColor.Red;
}
If I give fix Height then it look like this .
Output :
1. Give the below constraints to your view, height is according to your need. here I'm giving 80.
2. Change the height relationship.
3. Add aUILabel in your above UIview, and give below constraints.
--> leading, top, bottom, trailing to uiview and height i.e. 80.
4. set height relationship as you do with UIView.
5. Change the property of UILabel , Lines to zero
6. Now enjoy with your constraints.
EDIT: Add bottom constraint to your view instead of height constraint.
I don't see and bottom constraint added to UIView, so the view height will be 0.
If you have added the height constraint to UIView, there is a probability that UILablel might be overlapping the UIView, so you are not able to see the background color.
Set the UIView height constraint this will solve your problem
You can also add height or bottom constraint to your UIView.

Resources