I have a horizontal stack view, with an empty UIView on the left side and a label on the right side. In storyboard builder, it looks perfect (just look at the green row):
However when I run the app on Sim or device, the color view just collapses and disappears:
I have the stack view set to center alignment and proportional distribution.
If I give the color view a set width, it works well in Sim/device, however I get a warning in the interface builder, which annoys me. I assume there's a more correct way, but I don't know what that is. With set width warning:
It only allows me to delete the width=50 (the one I entered). It won't allow me to remove width=0 (not set by me, seems to be default).
Anyone have any ideas?
First, you set a proportional distribution, which tells the stackview: "Hey stackview, lay-out the views proportional". Then, you set a fixed width, so you are saying: "Hey stackview, give this a ... width". Both can not go together, since they are different.
Either make 2 stackviews, or add an UIView in to the stackview, and make that image proportional to his parent UIView.
So:
-Stackview
-UIView
-Image proportional to UIView
-Label proportional to UIView
-UIView
-Image pro...
-label...
-UIView
-Image...
-label...
And set your StackView to "Fill equally" to use this way.
Working with StackViews
A method that works is to make the strip of color beside the label an image and use UIImageView instead. StackView will then consider the UIImageView to have content and not compress it. But that will obviously cost more resources. Also to note that the images used for the strips have to be the same size or the StackView will compress them to different sizes the screen too.
Another is to set the Distribution property of the StackView to Fill Equally this will give the strip and label each half the space. It will work but may not provide the visual you are looking for.
Alternatives
By the amount of information provided, I see no requirement to use StackViews. You may instead just apply constraints that gives the strips and fixed width.
You can also try using auto layout by setting each strip to fix there distance to the leading and top while maintaining its size(actually the default settings) and the label to the same except also fixing its distance to trailing and width to scale with superview.
Related
I am making a note taking app in xcode8 for iOS 10.2. The note is consist of a textfield, textview and imageview. I am adding textview and imageview in separate scrollviews (to provide the facility of zooming and adjusting image). Then I have added both scroll views in a stackview to ensure that imageview and textview stands side by side in a landscape mode. To do that, I have added variation to axis property of stackview( width=any, height= compact and Gamut=any, and set that to the horizontal, as shown in right corner of screenshot to see view hierarchy without any constraints).
I have tried many constraints but, every time it fails to adopt. Let's take an example, I am adjusting size of the scrollviews on the size of content(by setting top,bottom,leading and trailing constraint), the stack view is adjusted to the main view. Now, the only thing that needs to be adjusted is text view and imageview with respect of stack view. But, here is the tricky part If I include a fixed trailing constraint of text view to the stack view; it will work in portrait mode.As soon I turn into landscape mode that constraint will not work(the trailing constraint which have 0 distance from stackview) because the edge will be side to the imageview not to the stackview(because I am putting image and text side by side as explained above) which will make textview larger than required, same goes for imageview's leading constraint to the stack view and vertical distance constraint betweem image view and textview.I think the root of the problem is I have made a variation to the axis of a stack view (in order to get text and image side by side in landscape mode) but, that was necessary part.Can anyone have solution for this? Do you think there can be other problem? Should I choose Intrinsic Size of scrollviews to placeholder option or let it be system default?
Thank you.
So I hope I understand the question and I will try to walk you through what I understand you hope to accomplish. I preface this by saying I just started using UIStackView because of backwards compatibility.
Note. To get the magic of ScrollView with AutoLayout I almost always embed them in another UIView. There are reasons to not but in this case you will see how valuable this is to AutoLayout.
Step 1) Drag your UIStackView and add Top,Bottom,Leading, and Trailing. Now add 2 UIViews and set the UIStackView to Fill Equally. It will now look like the image(Background colors to check your work).
Step 2) Now add a UIScrollView to each of these UIViews. Add Leading,Trailing,Top,and Bottom on each of these.
Step 3) Add a UITextView and UIImageView to the ScrollViews respectively. Now Autolayout is mad at us :( but we will fix that.
Step 4) Drag from the UIImageView to the View that is holding the UIScrollView(First Set of Views we added). See image
-Choose the option to add Equal Widths. See Image
Repeat the same step but add Equal Heights. Now add Top, Bottom, Leading, and Trailing to the ScrollView.
Step 5) Repeat exact Step 4 with UITextView
Your final view hierarchy should look like this.
Now you can rotate your UIStackView and do what you want I think.
And Horizontal
Side by Side Preview
I did add a <= 0.1 equal heights multiplier on the textfield at the top but I don't know if that was necessary.
Enjoy.
I implemented a viewcontroller similar to the one in this question:
iOS two views cover exactly half of parent view
I get the desired result. The problem is that when I add a UIImageView into those two containers, the result get resized and ruins the symmetry. How do I prevent Imageviews from changing the size of their containers? I need to use AspectFill for these images.
I don't think the containers' sizes are changed. You just need to set their clipsToBounds property to true to avoid overflow.
If you use Reveal you should see the containers' sizes are not changed even if pictures inside them are bigger than themselves.
I'm unsure I understand what you mean about adding UIImageView into those controllers causing the views to resize, so forgive me if I'm getting this all wrong...
It sounds as though you've created two views of equal height that, together, consume the entire vertical space of the screen. After having done that, you want to add one or more UIImageView's to each of the original two views. Unfortunately, when you add the UIImageView, the enclosing view is resized.
Assuming I have that correct...
Are you doing this with Interface Builder either in an XIB or Storyboard file? If so, you ought to be able to achieve this with the proper set of constraints.
In the following image, I've laid out what I describe above.
As you can see, I have a red view on the top half of the window and a green view on the bottom half. The red view contains a UIImageView that is 75% of the width and height of red view, with its origin at (20, 20) within the red view.
The scene is configured as shown below:
The constraints on "Upper View" are:
You can see from this that Upper View is flush with the left, right, and top of its superview, and that its space to Bottom View is 0. You'll have to trust me that Bottom View is set up the same way.
The height of the Upper and Lower views is "Proportional" as shown in this constraint:
To achieve this "Proportional" setting, you first make the height of Upper View equal to the height of the superview, and then edit the constraint, changing "Multiplier" from "1" to "0.5."
The height (and width) of the Image View is proportional to that of the Upper view, as shown here:
If you set it up this way, you ought to be able to accomplish what (I think) you are looking to accomplish.
If my original assumption of what you are trying to achieve is incorrect, please post images of what you've got and how it's not working.
I'm currently setting up a login screen that should ultimately look something like this:
I've successfully accomplished all the constraints needed to create the desired look on all screen sizes, however, I can not seem to figure out the constraint needed to correctly align the "Don't have an account? Signup". I've designed it so the "Don't have an account?" is a UILabel, and "Signup" is a UIButton. I've just aligned these side by side.
The UILabel, "Don't have an account?", has the following constraints:
The UIButton, "Signup, has the following constraints:
These constraints seem to accomplish what they need to on screen sizes 4" and below. however the 4.7 inch, and 5.5 inch (iPads excluded), have wide spacing between the UILabel and UIButton. I've read Ray Wenderlich's tutorial on auto layout, and still can not figure out the problem (I'm new to auto layout, but I have an idea what I'm doing. I'm not just adding random constraints hoping it works).
This is what it looks like on all my targeted devices:
Notice as screen size increases, so does the gap in between the label and button. Any help is appreciated.
You are setting the leading space of the label to its superview, and you are setting the trailing space of the button to its superview. So obviously if the superview gets wider, they are going to get further apart.
So if that's not what you want, don't do that.
The actual solution to what you want to do is quite tricky. You want these two objects to behave as a group, and you want that group to be centered. There's no simple way to express that. You will need to make a group. In other words, you will need a container view, give that view an absolute width and center it, and put these two objects inside the container.
New in iOS 9, a UIStackView can help you with this.
Another approach that works is to use a couple UIViews as spacers. I sometimes prefer this to containment, but it is probably a matter of taste.
Remove the leading constraint from your UILabel.
Remove the trailing constraint from your UIButton.
Add a UIView with clear background in front of your UILabel. Set a leading constraint from this UIView to the container leading edge with constant 0. Set a trailing constraint to the UILabel with constant 0.
Similarly, add another UIView after your UIButton. Set a leading constraint from this UIView to the UIButton with constant 0. Set a trailing constraint from this UIView to the container trailing edge with constant 0.
Both UIViews will need a Y position and height. These are somewhat arbitrary so I would set Align Center-Y constraints with your UILabel, and height constraints of say 5.
Here's where the magic happens: select both UIViews and set an Equal Widths constraint. This forces the UIViews to occupy equal space on both sides.
UIStackView is overkill for this situation. Just
Put the label and button in a single UIView.
Constrain the label's left and center Y to the container view.
Constrain the button's right and center Y to the container view.
Constrain the label's right edge to the button's left edge.
Set the horizontal content hugging priority of the containing view to 1000.
Constrain the containing view's center X to its superview.
You can do it to your existing code only by setting few constraints. And this would work on all resolutions even on the iPad. You don't need to group them , i have attached the images to show the constraints that i have applied.
And for the button set this constraints
It would be shown properly on all the devices kindly have look as to how it looks on all the resolutions and also in the landscape mode of each resolution
Thanks
Omkar
Hey, I'd like to obtain what you see in the pictures: in Compact Height mode (landscape iphone) both the red and the blue view have to take all screen vertically and half the screen horizontally. In Compact Width mode (portrait iphone)they have to take all the screen horizontally and half the screen vertically. Space between views should be same size in both modes.
I used to think I have to use size classes and auto-layout constraints, but everything I tried failed miserably.
Maybe I have to use a UICollectionView and change flow direction based on orientation (if that is even possible)?
A collection view is probably overkill, because you don't want scrolling and that's the whole point of a collection view--by the time you do the sizing to stop it you'll have done all the work necessary to set a non-scrolling layout.
This is possible with Size Classes in IB. First, In general you will probably find it helpful to name the views in the Document Outline on the left in IB. You will also want to use this outline rather than try to grab the tiny constraint H-lines.
Set up all the constraints except 1) constraints linking the
OrangeView and BlueView to each other, 2) the constraints linking
the OrangeView to the top and left(leading), and 3) The constraints
linking the BlueView to the bottom and right (trailing).
Change the size class setting at the bottom to w-Compact and
h-Any in the funky box system. Now we're designing for a compact width, so views on top of each other.
Create a constraints for vertical space for BlueView.bottom to
OrangeView.Top. Also create constraint for OrangeView to
superview.leading (or ledaing,margin) and BlueView to
superview.trailing.margin. If you select any one of these constraints and look at the Size Inspector on the right (the ruler) you should see an "installed" checkbox not selected, and below that a w-Compact h-Any and another installed box, this one selected.
Now, while keeping the constraint selected just to see what happens, change the sizeClass selector at the bottom to w-Regular h-Any. Notice that in the Document Outline to the left, it should get grayed out.
Now we are designing for regular, so side-to-side. Add constraints linking the views for horizontal space, BlueView.trailing to OrangeView.leading. Also link OrangeView.top to the superview.top or top aligned to BlueView.top, and same for bottoms. You can manually edit the frame first; if not, IB will automatically fill in the wrong values, so edit these after you create them, and verify they are w-Regular and h-Any. With the ViewController selected, select "update frames" and the views should snap to their expected shape for the size class.
Let us know if this works for you or if it was unclear. Good luck!
I'm new to autolayout and i'm kind of stuck on how to center these 4 images in all different devices like it looks on the images. i've tried to apply the auto configured constraints but then it will have that distance and that does not fit on all devices. So my question is what constraints do i need to apply on all different images in order to make all image centered with same distance?
Here is how my cell in storyBoard looks like:
image of the constraint options on image 1:
image in simulator:
/// MY TRY ////
Here you can see the constraints that i've added and the result?
result:
Your approach is almost correct, it simply lacks size constraints for the images.
If you want to dynamically resize the images and keep the space between them constant, put constraints on the images for the width to be >=20(or any other value, depends on your needs) and a constraint for keeping the aspect ratio. Then ctrl-drag from UIImageView1 to UIImageView2 and set a constraint for equal widths. Repeat that from UIImageView1 to UIImageView3 and from UIImageView1 to UIImageView4.
If you want the images to always keep their fixed size and dynamically sized spaces between them you need another approach:
The trick here is to place 3 empty UIViews between the UIImageViews so that it looks like this:
Set constraints to the top for all views
Set constraints to the left and right for UIImageView1 and 4
Set constraints for all UIImageViews to the same width
Set constraints for all UIViews between the UIImageViews to the same width
Set constraints for all the distances between the views to 0
Set the width constraints for the UIViews to >= 0
This way makes the empty UIViews between the UIImageViews to resize dynamically and all the same width.
I hope you get the idea.
For the first image add a leading space to superview and for the last image add a trailing space to superview and add vertical spacing between first and second, second and third, third and fourth and also set horizontally center within the container to each of the images
The objects on your storyboard require at least 4 constraints per object.
When there's orange lines around the UIImageView object like appears in your question, this means a constraint is missing, or conflicting and can often mean the image does not display at runtime like you'd expect.
In the first instance I recommend you select all objects and 'clear constraints', then start again.
Although not exactly the same, here is a link to an answer which explains the auto-layout constraints in a bit more detail. Once you understand it, auto-layout can be very powerful.
>>Link to similar auto-layout issue - iOS CustomTableViewCell: elements not aligning correctly<<
I hope this helps
If you want the images to always keep their fixed size and dynamically sized spaces between them then very easiest way first you drag the four UIView in your StoryBoard
set constrain top left right and height for all the UIViews and give the equally width to all the UIViews(drag from one UIView to another and sets its equally width repeat this work for all the UIViews).
Image about layouts
Secondly you have to drag your images set in these UIViews and sets their constrain height width and centre horizontal in container and centre vertically in container.
In last set the background colour of all UIViews default(white) you get the result it will work....i assure.
Screenshot of Xcode