I tried to create a custom freefrom view with interface builder.
I have a UIView which is containing a UIImageView and UILabel.
I set the constraints to adjusting the Label according to the Image etc and a margin to the superview.
Now I want the superview to exactly fit the subviews. But when I press Editor -> Size To Fit Content, the superview is not resized completely and the constrains are in conflict. What there appears is a implicit constraint ("iPhone Portrait Screen Height"), which can not be altered/deleted. See Screenshot below:
While not ideal, depending on how your XIB is structured and how you are referencing the view, you could create a "scratch pad" view and place your custom view inside of that just to see how everything will layout. That is if you're setting the view to an outlet defined in the XIB's File Owner, you can just connect it to the view you've created inside the "scratch pad".
For example, I created a container view with a square and a switch inside. The top example complains of conflicting constraints and doesn't layout correctly, while the bottom example shows the same thing centered in a throw-away view. Again, not ideal, but it's working for me.
Edit: I just realized that some size class constraints may be lost once the "scratch pad" view is discarded so that is another wrinkle to consider. Still looking into this.
Just to make it simple forget the label for the time being. You have already added the width and height constraint of the image view, now instead of using sizetofit content, try adding leading, trailing, top and bottom constraints between the image view and it's parent view. With that your parent view should fit the image view.
The same technique (constraints to parent view) can be used to get it work with the image view and label together.
I noticed that when I physically dragged the superview's width and height to satisfy the constraints, the red constraint errors went away along with the "iPhone Portrait Screen Width" constraint. In other words, my constraints dictated that my subview be bottom aligned with its super view. If I dragged the superview's bottom edge up to align flush with the subview, the errors went away. Still seems buggy and unintuitive.
Related
Swift 5/Xcode 12.4
My app uses a UIScrollView to zoom its child UIImageView (which is filled through code). This part works but the ScrollView keeps complaining in XIB that it's missing constraints for the x/y position or width/height.
As you can see, the ScrollView has a top, leading and trailing constraint and the width is set to equal the height. From my understanding it knows its dimensions and position because of these constraints but apparently it's not enough. I do NOT want to center the ScrollView vertically and as the app has to support both iPhones and iPads, I also can't just set a fixed "bottom space to" constraint for the ScrollView.
I already tried to set the ScrollView's width to the ChildView's width and center it horizontally in it but the warning still didn't go away.
I've seen suggestions to put the ScrollView's contents inside another UIView but in my case it's only a single image and if I embed it inside a view, then the zooming breaks.
Why is the ScrollView still missing constraints and how do I fix it (without changing the overall layout of this ViewController)?
A UIImageView (without an image) has no Intrinsic Content Size.
If you're going to be setting its Width and Height constraints via code, but you want to get rid of the IB layout complaints, give the image view a Placeholder:
Edit
If you want the view(s) to be sized in IB, but you're going to change the constraints at run-time, you can either:
Connect the constraint to an #IBOutlet and change the .constant via code (more problematic to change the multiplier if needed, so probably not the way to go)...
Or...
Give the view constraints in IB but set them as Placeholders by checking "Remove at build time":
I am using autolayout in Xcode and am creating a fairly tall (1300px) ViewController with a uiscrollview to navigate up and down. I made the viewcontroller freeform so its dimensions are [375,1300]. I then incorporated the scrollview, added the content view as well as all the subviews & constrained everything, leaving no constraint errors. At runtime there are no errors, but everything is all smushed into the normal screen size when I intended for it to be very tall (~1300px) and scrollable. Any clue as to what I am doing wrong?
Below is a diagram showing the issue where:
The Outer Black Blox is the ViewController's view
The Inner Black Boxes are subviews
and The Blue Box is what is displayed on the screen
Yes, your correct #Ryan Cocuzzo. I think you need to set sub view priority from 1000 to 250. See below screen shots.
1) Select height constraint of the subview
2)Then go to show to size inspector
3) Now change the priority constraint from 1000 to 250.
4)Finally you get like this
Make sure the following are true:
The 4 content views are subviews of the UIScrollView, not your view controller.
The autolayout constraints on the 4 content views must reference the UIScrollView only, not the view controller's view.
The 4th box cannot have a bottom constraint.
It looks like the 4th box has a constraint to make it's bottom align with the bottom of the view controller's view. This would force the other views to smush up together. The 4th box also cannot have a bottom constraint so that the scrollview can resize itself to encompass it's subviews.
I am learning constraints and spent whole day applying them to the following screen.It is not getting displayed properly in landscape mode.Basically i am not getting how to fix vertical space between ,say, label-Welcome to BBBB and textfield-username so that textfield always appears below the label yet the spacing between them is adjusted according to the screens of different size. If i go for Pin\Vertical space, it automatically fixes the constant value.
Remove the label (or just move it out of the way).
Fill the space that you want to resize with a view.
Constrain this view to the objects above and below and to the sides of the parent view.
Put your label into this view and constrain it to the top of this view and centred to it.
You may need to change the constraints on the objects above and below it to stop them from changing height in an unwanted manner.
This new view should now resize as the device changes orientation but the label should remain at the top of it.
Repeat on other areas of your layout (i.e put things that are not moving around as you want them into sub views and constrain these views to resize accordingly). Experiment with using variable heights, fixed heigh constraints and 'equal heights with' constraints on the views that you add to get them to resize as you need.
Edit: but you have a lot of vertically stacked items in that view - you may never get them all to fit into a horizontal orientation. You may need to remove a few, or add a scroll view or force that view only to layout in portrait mode or... Don't forget to check that it works on all devices you are targeting.
#Ali Beadle was right. Since i had a lot of vertically stacked items, lining them up in landscape mode was not possible. So, i went for scrollview.
I have taken a ScrollView first and then a UIView named ContentView on that ScrollView. I have made the width of ContentView equal to the width of parent UIView and kept its height fixed to 568. In my code i set
_contentViewHeight.constant = self.view.frame.size.height;
Now it scrolls in landscape mode while in potrait mode, it does'nt scroll.
I run into Autolayout problems all the time. But I finally figured out a way to overcome a lot of issues that arise from it.
I simply will use a container-View like ScrollView or even a plain old UIView, place all my controls in it. thats it. this makes things a lot easier for autolayout to figure out the constraints. in your case you could just use a UIView.
-start off by removing all the constraints you have I would start by selecting each control in the XIB and see if it has width/height constraint, select it then press the delete key then at the bottom of the project explorer you'll see all the constraints that auto layout has select each one then delete. that should get rid of any complaints that auto-layout might have.
-Place a UIView object inside your main View then
-move all the controls inside it. Then
-add the necessary constraints for the container view so it'll resize in different orientations and don't worry about any constraints inside the container view (auto layout will figure them out automatically).
that does the trick for me usually.
I have trouble implementing scrollview with auto layout:/
Here is simple "Hello World" project with that problem: http://www.sendspace.com/file/cg96by
But the problem… I need to create scrollview, but also I need to use auto layout. So I created pure single view application, added (like I saw in some tutorials) Scrollview (the same size as main view), added constraints (all zeros) and then add Container View (the same size as scroll view), add constraints and.. It's didn't work:/ It doesn't scroll. Here is the screen of that situation:
Now, when I delete two constraints named: Center X and Y Alignment (marked on the screen), it works perfectly, but Xcode5 doesn't quite like it :/ and shows some errors like on the next screen below.
Why does he want width and heigh 0 ?!
Actually ContainerView doesn't matter. I've also tried with image view. When you select "Add missing constraints" it also add Center X and Y Alignment. And scroll doesn't work. When you delete them, scroll works but you have this warring:
Ok, I find manually adding the autolayout constraints to be quite confusing, using the "Add New Constraints" button at the bottom really comes in handy, try this, after you get each view where you want it use that way of adding layout constraints for each view (ie scrollView, containerView, UIImageView) I did this, and heres the example, select each constraint as I have so that the top, left, bottom, and right edges are set, this should do exactly what you want.
You will probably want to erase all your current constraints and then implement them this way.
heres the layout like you want http://cl.ly/image/463k2043401L
and heres the example adding the constraints: http://cl.ly/image/472l2V0l3N1L
To keep it dynamic so that you can rotate it, you will want to do the above for all view BUT the container view... then If you control drag from container to scrollview with no constraints, you can add all of them that it suggests except for the height and width at the bottom, that satisfies any missing constraints and should do the trick, It will center the container inside of the scrollview and keep it pinned to the top, bottom, left and right, and it should dynamically change with your scrollview content size.
http://cl.ly/image/1o3k1e452W0g
Sorry for the confusion, hope this helps!
I had a similar problem and i found relative simple solution from within Interface Builder using pure Autolayout without any code.
For proof-of-concept at first remove any constraint in View Controller to if see this works.
This is sample layout:
View (main view of my UIViewController)
Scroll View (UIScrollView)
Container View (UIView)
Content View (e.g. UIImageView)
A. Scroll View width/height should be smaller that Container View width/height
B. Container View should have some determinated width/height (may be explicit width/height )
C. Do Control-drag Container View to Scroll View and add only:
Leading Space to Container
Trailing Space to Container
D. Check out those two constraints and set "constant" value for both to 0
E. Run app and
I am attempting to layout a screen design using constraints (auto-layout) from interface builder and hope to avoid coding constraints, but I would accept an answer for either case I guess.
I have two subviews in a contained in a top level view. I want to fix vertical distance of the first subview to the top of the screen (I was able to accomplish that - common use case for a vertical space constraint). I want the second subview to float (vertically) in the center of the distance between the bottom of first subview and the bottom of the screen. The idea is that the design responds somewhat to iPhone 3.5" vs 4" dimensions.
I am having trouble defining a constraint or set of constraints that would accomplish this.
I have tried setting inequalities on the vertical spacing constraints between the second subview and the top of it's neighbor (the first subview) and the bottom of the superview, and playing with the priorities of those constraints.
An idea that was suggested in a few other related posts on SO is to use a container that is pinned to the bottom of the screen, as well as the pinned to the bottom edge of the first subview, and then center my second subview in the container. I was hoping to avoid complicating the view hierarchy if possible, but maybe that isn't easily avoided.
Any thoughts or suggestions?
UPDATE
This answer describes how to do this in Xcode 6.0 (and probably works in Xcode 5.0 and 5.1).
ORIGINAL
If you want to do this with auto layout, you have to add at least one spacer view. It doesn't have to be the superview of the vertically-centered view (or any other view), so it has a pretty minor effect on your view hierarchy.
I recommend not trying to set up constraints in Interface Builder in Xcode 4.6.3. It's just too painful. But if you really must, this is doable.
Create a spacer (a plain old UIView) from the bottom edge of the top-hugging view to the bottom edge of superview. Set it to hidden. Give it constraints to the top-hugging view and the left and bottom edges of the root view, and pin its width. My spacer width is 10:
Add your middle view (here, a button). Give it a “Horizontal Center in Container” constraint. Then select both the middle view and the spacer view and give them a “Vertical Centers” constraint:
Note that if you drop the middle view when IB is showing the correct guidelines, it will set these constraints for you.
You can test by enabling resizing for descendents (but not siblings & ancestors) and resizing the root view in IB. The middle view will remain centered between the top-hugging view and the bottom of the superview: