I am attempting pretty much the same thing as the OP of this question in Xcode7.
My end goal is to have a vertical StackView with two child views: one that occupies 70% of the parent's height, and one that occupies the remaining 30%.
I followed the instructions in the post I linked. I selected the child view (which is a GMSMapView) and the parent StackView and checked the equal heights box in the Pin constraints menu. That worked just fine and dandy. However, when I edited that constraint from the GMSMapView's size inspector and changed the multiplier to .7, suddenly I get a conflicting constraints error!
Here is a picture of the scene I am working on right now:
And here is a picture of the error:
Does anyone know how to resolve these conflicts? I tried turning off Autoresize Subviews but I am not sure that worked since I can't delete some of the constraints displayed in the error message.
The height of a UIStackView is based off of the size of its subviews (Unless your using UIStackViewDistributionFillEqually).
The first two conflicting constraints evaluate to this
Stack View.height = View.height
Map View.height = 0.7 x Stack View.height
But since the UIStackView bases its height on its subviews, there is essentially a third constraint.
Stack View.height = Map View.height
All of these constraints can not exist together since they conflict.
There are two options I can think of.
Remove the UIStackView. Since it only contains one view, you aren't getting any benefit from using it and it's only complicating things.
If that's not an option, you will need to remove some constraints so that you aren't constraining the UIStackView to a specific height.
Related
Hi every one actually I want to fit this scroll view and stack views on simulator correctly but unfortunately this result not things that I design to view controller and here is my constraints :
if you have any idea , please share thank you so much.
here is when I result after the answer :
The problem is Stack View.height = height, StackView's height should be automatically driven by it's subviews.
After you remove this, you should see another issue that's caused by Stack View.centerY = centerY - you should be able to remove this as well and you should get the expected behavior with rest of the constraints in place.
UPDATE :
From the screenshot, it appears that you are using Distribution = Fill Proportionally for the StackView, and it will require a height constraint to distribute it's children proportionally within that height. You should use Distribution = Fill and it will NOT require the height constraint anymore.
UPDATE 2 :
According to the 2nd screenshot, your ScrollView height is not defined. You should set something like ScrollView.bottom = superview.bottom which will tell ScrollView how tall it needs to be. Once your ScrollView height is defined, it should go away.
Simple goal, but it demonstrates situations where Auto Layout gives me a headache. I want to have a stack view with a width of 256pt and a dynamic height based on layout (I shouldn't have to manually specify the height).
Inside it should be an image view sized 64pt x 64pt, which should also be centered horizontally as well as constrained 8pt from the superview's top. Note that the image view isn't the only child, hence why the stack view's height must be sized dynamically.
Auto Layout now tells me there's a conflict between the 256pt width constraint of the stack view and the 64pt width constraint of the image, as well as some mysterious "leading = Image.leading" and "trailing = Image.trailing" conflict which I can't even delete nor find.
Am I missing out something here regarding Auto Layout? I expect all logic to be contained in the interface builder, so no code should be required.
Running Xcode 9.1
Layout image
There is nothing to confuse. iOS clearly telling you the issue.
StackViews take size based on the size of child components (this is called implicit size) unless its been overriden manually as in your case which is 256pt.
Because stackView is just a container for multiple childViews stacked either horizontally or vertically, now because you have added only one imageView to it, it adds the leading and trailing constraint to it which makes absolute sense because you added a single view to the stack of view's , now what should stackView do? stretch childView (in your case imageView) to its own size.
But then you did not allow it because you added width constraint to imageView now when it tries to increase the imageView's width imageView's constraint wont allow it.
Hence it is complaining that there are too many conflicting constraints. Thats all :)
some mysterious "leading = Image.leading" and "trailing =
Image.trailing" conflict which I can't even delete nor find.
You cant delete them because, imageView is the only view inside stackView. Because there is only one child view to stack, stackView will start from left side (leading) to right side (trailing). Because now stackView has its own width it tries to change the width of imageView to reflect the same! But images width constraint prevents it from happening.
What are you trying to achieve with imageView added to stackView. If there is only one view in stackView, adding stackView does not make any sense. Reconsider what you are doing.
Finally, when you have only one childView in stack view, adding horizontal center does not make any sense (no matter vertical/horizontal stackView).
Either I'm out of my mind, or AutoLayout is straight broken. Can someone please explain this to me. I have a TableViewCell in a TableView that spans the width of the ViewController. I put 4 Labels inside my TableViewCell. I created constraints using AutoLayout such that each label is 25% the width of the TableViewCell. And yet, the 4 labels are CLEARLY different widths and they don't even add up to 100% of the width of the entire cell. Here's the screenshot. (Horizontal position of each of the labels is ambiguous, yes, but that shouldn't make a difference). Why are they not the same width? And why does 25% + 25% + 25% + 25% not add up to 100%? Running XCode 7.2 and targeting iOS 9.
This red error symbol is Interface Builder telling you that it cannot solve your constraints. In this case, as you have said, it's likely because you have not provided x position constraints for the labels.
Auto layout can either solve all constraints and get a right layout, or it can't and the result will be undefined. Remember that auto layout is an algebra-based process that solves for unknown values by using known values that you provide in constraints. If you don't provide sufficient and unambiguous known values, the equations for the remaining values simply cannot be solved and there can be no expectation of a correct result. The solution is to create enough constraints to make the layout solvable.
As a note, as of iOS 9 I would suggest using a UIStackView to hold those labels. UIStackView exists precisely to take the pain out of setting up manual constraints for these types of scenarios. If you used a horizontal stack view in the cell, you would constrain its edges to the cell's edges, drag the 4 labels into it and set it to "Fill Equally". And that's all you would need!
Daniel Hall's answer has useful information, but doesn't tell you specifically why you're seeing what you're seeing, so I will.
Xcode doesn't always enforce your constraints in the storyboard editor until you ask it to. In this case, you can select the table view cell's content view and from the menu bar choose Editor > Resolve Auto Layout Issues > All Views in BBRowTableViewCell > Update Frames. (Sometimes it takes two or three tries for Xcode to get everything right.)
However, you probably won't like the result. Because you haven't constrained the horizontal positions of the labels, Xcode will probably pile them all up at the left edge of the cell, or maybe somewhere outside the bounds of the cell where you can't even see them.
If your deployment target is iOS 9 or later, the easiest solution (as Daniel Hall said) is to put the labels in a UIStackView set to “Fill Equally”, and constrain the stack view's edges to the cell content view's edges.
If your deployment target is earlier than iOS 9, then you should create the constraints described by user3802077.
This is not the only way, but here is how I usually do it.
As you did for the top and bottom for each labels, then:
Leading of label1 to leading of superview
Trailing of label4 to trailing of superview
Then a constraint for each neighbouring label:
label1.trailing to label2.leading,
...
Then put an equal width constraint from each labels to label1:
label2 to label1
label3 to label1
label4 to label1
This should be it. No need of specifying 25%.
For autolayout constraints it requires to give for constraint to particular object
x,y position and hight , width
If you are not giving any one of this it shows error to you.
So make sure to give all the require constraints to your object.
Other option is uistackview for the ios 9 and later.
Here is a link for you to learn about stackview
https://m.youtube.com/watch?v=XqVWyA5PLwk
I have:
application, that should work in landscape and portrait mode.
view with full-size scroll view on top.
some view inside scroll view with fixed width and height. (with added H and W constraints)
set to view inside scroll view as horizontal centered in container. (added according constraint)
I have warning in interface builder "Has ambiguous scrollable content width".
The only way to fix this problem, that I know - is set trailing and leading constraints.
But for different iPhones (5.5", 4.7", 4") I need to set different trailing and leading constraints.
How can I eliminate this warning and still have centered horizontally view with fixed W and H for all iPhone sizes?
I create Github repo to illustrate this problem: ScrollViewAmbigous
This is not duplicate of UIScrollView Scrollable Content Size Ambiguity
, but it similar (and not answered although), but this question especially related to different sizes of iPhones.
In the morning with a fresh cup of coffee I figured out workaround for this issue!
So, here is the initial state for simplest case:
scrollView with 0 constraints to all edges
Button centered Horizontal and Vertical with fixed Width and Height
And, of course Has ambiguous scrollable content width and Has ambiguous scrollable content height annoying warnings.
All, that we have to do is:
Add 2 additional constraints, for example "0" for trailing and/or bottom space for our view (in my case - UIButton)
Important: you have to add trailing and/or bottom constraints. Not "leading and top" - it's not works!
You can check it in my example project, that demonstrating how to fix this issue: ScrollViewAmbigous
P.S.
I don't know why it works and how Xcode detect which constraint is more prioritised (because I'm not set priority for these constraints explicity), but I'll be thankful if someone explain, why it works in comments below.
Problem :
The warning is telling us that the the content size of the
scrollview depends on its subviews.
while your subview don't have any strict rule of position and size (no fixed constraints) it will confuse nib generated scrollview
content size.
Solution :
Make only one subview as a 'contentView' for scrollview.
Add strict (fixed) constraints to that 'contentView'.
Best practice : equal width and height to its scroll view.
Add all other subviews and constraints to your 'contentView'.
There seems to be a lot of confusion on this issue. My take is that a UIScrollView must have TWO trailing space constraints, an 'inner' one connecting it to one of it's subviews (so it can know its content width), and another 'outer' one connecting it to a sibling or superview so it knows its frame width.
Same principle applies for height, i.e. two bottom space constraints.
I have a UIViewController on my storyboard that has 2 subviews side-to-side horizontally. I added constraints to fix the leading and trailing edges to a constant (20 pts), and another constraint to keep the widths equal. If I assume the following, it should be possible to calculate what the width of each subview will need to be:
the subviews do not overlap
there are no other views present (horizontally, at least)
the width of the screen (the superview) is known
However, XCode gives me a warning that my views are horizontally ambiguous. I'm guessing that means that XCode is not making one of these assumptions, but which one is it? And is there a way for me to instruct XCode to make that assumption?
EDIT: Okay, played with it a bit and got the warning to go away, but it looks like it's not making the first assumption - it's just setting each subview's width to superview.width - 40, and happily burying one view underneath the other. So the question is how to I stop them from overlapping?
EDIT 2: Okay, my actual screen is a lot more complicated than my simple example. Here's what I got:
So in this setup I have 4 views that are vertically and horizontally staggered. I want the blue, red, and purple views to all be the same subview.frame.size.width = superview.width - 60. The blue and purple are lined up in the left column, and the red is alone in the right column, and all the gaps (between the two columns and between each column and it's nearest edge) are at a constant (20 pts). These 3 tables have a variable height, which I will be setting programmatically as described in James's answer here. At the bottom is a pink view that stretches the width of the screen (minus gaps), and sits at a constant 20 pts below either the purple or the red view, whichever is lower (which I'm attempting to do by giving it a spacing constraint of >= 20 to each view, and I hope that it will pick exactly 20 for one of them). Since all of the heights are dynamic and may not necessarily fit on the screen at the same time, I made their superview a UIScrollView instead of the normal UIView.
When all is said and done, I'm still getting a warning that all 4 of my views are horizontally ambiguous, and that the pink bar is vertically ambiguous. I think it's having trouble realizing what is supposed to go next to what, which is why it thinks it's horizontally ambiguous. And I think it's not picking to place the pink bar exactly 20 pts below either the purple or red views, which is why it thinks it's vertically ambiguous. Can anyone confirm or deny any of these suspicions? Or suggest a way around it? When I run it in the end, I just get this (I made the background of the scroll view yellow, which you can't tell in the storyboard screenshot):
Vertically Ambiguous
Okay, I think I've solved the vertical ambiguous part. I added two vertical constraints between the pink and purple views and two vertical constraints between the pink and red views. For each pair, the first constraint is that the spacing between them must be > 20 pts, and it has 1000 priority. The second constraint is that the spacing is = 20 pts, but it only has an 800 priority.
For example, if the bottom of the purple view ends up being lower than the bottom of the red view (as it is in my first screenshot), Xcode should try to set the vertical distance between the pink and red views = 20, but it will realize that that conflicts with condition that the space between the purple and pink being >= 20. Since the >= constraint has higher priority, the = constraint will be ignored. Now, when Xcode looks at the constraint that the spacing between the purple and pink views being = 20, it checks that against the constraint that the pink and red must be separated by at least 20. Since the bottom of the red view is higher than the bottom of the purple view, the >= 20 constraint between the red and the pink still passes.
So TL;DR, you can set up a view to have a spacing at a given value (x) from the most extreme of multiple views by giving it a >= x constraint with 1000 priority and giving it a = x constraint with <1000 priority for each view you are considering - and my vertical ambiguity problem has been solved. I do not yet have a solution for the horizontal ambiguity for all 4 of the views.
Horizontally Ambiguous
Okay, I got the horizontally ambiguous part fixed now as well. What it boils down to is that constraints in scroll views (and therefore table views) work differently than they do for any other kind of view. Here's what the step-by-step looks like.
Place the UIScrollView
Place a UIView into the UIScrollView to serve as a "contentView" for that scroll view
Add constraints to pin the contentView to all 4 corners of the scroll view AND pin it's width and height (so 6 constraints between the contentView and it's superview - 2 more than usual). Note that the width and the height can be pinned to something much larger than the normal screen size, which is probably why you are using a scroll view to begin with.
Add all of your other views you want in the UIScrollView (UIButtons, UILabels, etc. - I'm just going to assume UILabel from here on so I don't have to type as much, but any kind of UIView subclass will work) as subviews of the contentView, NOT directly as subviews of the UIScrollView
With this setup, the UILabels that are given constraints to their superview will constrain to the contentView, which has a defined size, so nothing is ambiguous.
Alternatively, if you want to fix the sizes of your UILabels (or dynamically calculate them, depending on the functionality of your app) and let the contentView expand to hold them:
Place the UIScrollView
Place a UIView into the UIScrollView to serve as a "contentView" for that scroll view
Add constraints to pin the contentView to all 4 corners of the scroll view AND pin it's width and height
create an outlet for the width constraints on the contentView (let's say we name it contentViewWidthConstraint)
place the UILabels
fix the sizes of the UILabels
create an outlet for the width constraints on the UILabels
Then in the code for viewWillLayoutSubviews
add up the widths of all of the UILabels and any gaps you want between them (as a CGFloat, which I'll call totalWidth)
set contentViewWidthConstraint.constant = totalWidth
And you're good to go! Note that I assumed you were setting the width in most of this example, but it should be just as applicable to height.
The problem is that many different widths of the two views will satisfy the constraints that you've set up. Here are two examples (I drew the shapes stacked vertically to make it easier to see the overlap example):
You can add a horizontal space constraint with a value of 0.