iOS and interface builder: misplaced view (e.g. UITableViewCell) - ios

I am using interface builder to create a masterview details application. However
when I run the app the cell gets misaligned.
Here is how it looks both on the simulator and on interace builder:
Any suggestion on how to fix this?
I have noticed that this happens also in the detail view controller that's why I choose the title of "misplaced view":

The problem in the first screen shot seems to be that you are not supplying a tall enough height for the cell. Thus some of the views on one cell are actually appearing on top of the cell below it. You need to fix your table view's rowHeight.
In the second screen shot, it looks like you are using auto layout but you are not doing auto layout (you have no constraints). You need to position these interface elements with constraints.

Check your constraints in interface builder first and make sure that your UITableViewDelegate is returning the correct heightForRowAtIndexPath:, then report back.

In Interface Builder, if you select one of these views that is not sized correct and then select the "size inspector" tab on the panel on the right (option+command+5), if you have no constraints defined, IB will warn you:
The selected views have no constraints. At build time, explicit left, top, width, and height constraints will be generated for the view.
If you don't see that sort of message, your screen snapshots suggest that you likely have constraints defined for the view which are tantamount to the same thing, left/top/width/height constraints.
The problem is that when you transition to a real device with different width, the layout of the view will not be correct.
If, however, you defined your own constraints (for example, notably using trailing constraint instead of width constraint, using bottom constraint rather than height constraint), you'll find the views will be better adjusted for the device's actual dimensions.
In your first example, iOS 8 will automatically adjust the row height of the cell if you had defined constraints. Something like:
V:|-[nameLabel]-[artistLabel]-[categoryLabel]-[priceLabel]-|
V:|-[imageView]-|
H:|-[imageView(100)]-[nameLabel]-|
H:[imageView]-[artistLabel]-|
H:[imageView]-[categoryLabel]-|
H:[imageView]-[priceLabel]-|
I'm showing it to you in VFL, but you can define it in IB, too. The key point is add constraints so that the vertical height is now unambiguous (i.e. the cell height will be adjusted to fit the labels) and the width is not hard coded, but rather the labels will expand/contract to fill it depending upon the device size.
Conceptually the exact same problem occurs in your second example, that you don't have leading and trailing constraints, but rather IB has defaulted to using leading and width constraints, which will not work as you go from device to device. For example, if you just want the text view, but have it adjust for the size of the device's screen, you might have constraints equivalent to the following VFL.
H:|-[textView]-|
V:|-[textView]-|

Related

Design Self-Sizing UITableViewCell using .xib, cell doesn't adjust itself in interface builder

I'm trying to use .xib file to design a self-sizing UITableViewCell. However, the cell doesn't adjust it's height according to it's content subviews. I have to adjust cell manually. If the cell is too large, a subview will be stretched to fill the cell. And if the cell is too small, there will be some constraint error alert by interface builder.
The UI is correct when running, but is broken when designing.
When using a .storyboard file to design a self-sizing cell, it works great. The cell can grow or shrink automatically.
Is this a limitation of the .xib file? Or did I miss something?
If you set constraints properly, the UILabel will be set its height and width as per the set constrains and its content.
All you need to do is...
For the first label you need to set Leading, top and trailing constraint
For the second label you need to set Leading, top constraint with the bottom of first constraint, and finally trailing and bottom constraint to the superview.
Do not forgot to set the number of line equal to zero & Line break mode to Word Wrap in the Attribute Inspector.
Also need to set the following
We could consider it a "limitation" ... but it's more a matter of "by design."
When laying out UI elements in Storyboard (including a Prototype Cell), Interface Builder (IB) does a lot of additional work. For an obvious example, you can change the Orientation and your prototype cell will automatically expand its width.
When developing a XIB, though, IB doesn't change your root view's size on its own. Think of it as IB saying "you're designing a XIB, you know what you're doing and you know exactly what you want."
While it's generally a good idea to follow IB's advice and get rid of any "constraint error alerts" it's not required.
There are legitimate instances when designing a cell (or other view) in a XIB where you cannot eliminate all constraint warnings. For example, if I put a UIScrollView in my cell XIB, but the scroll view will not have any content until run-time, IB will tell me it has "Ambiguous scrollable content size." In this case, I know my constraints are correct, and I know the content size won't be defined until I add and constrain subviews at run-time... so I can ignore the warning.
If you find it a hassle to manually resize the cell, but not see constraint warnings, you can (for this example) if your bottom-most constraint is Zero, give it a Priority of 999, or set it to >= 0 ... or, change the Ambiguity option to either:
or:
First set top, left, right constraints of first label and bottom, top, right, left constraints of second label with cell.
Set Lines of labels to 0 then it will work as you are expecting.

Constraints in ios

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.

UICollectionView change flow direction on rotation

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!

Using Auto Size class hides the view

Following is screenshot of my xib :
And this is what appears on simulator :
I don't know why some part of the view is hidden although I have used wAny hAny.
When using auto layout, it's best, in almost every case, to add them yourself, rather than letting the system add them for you -- the system will do that if auto layout is on (Which it is by default) and you don't explicitly add constraints. If you add a view to the canvas, select it, and switch to the size inspector, you will see this message,
The selected views have no constraints. At build time, explicit left,
top, width, and height constraints will be generated for the view.
If you are using wAny hAny, a view that's near the right edge of the view is going to get a constraint to the left side that will be very large, something like 500, so that will be off screen on any phone. You need to add your own constraint to the right side instead.

How to change uiview's height using auto layout?

So I created this scenario in order to understand how views increase in height according to their content. However am still not able to make it happen.
This is what I have now:
the textview is growing according to content. however the uiview containing it is disappearing. what constraints should I use so that when the uitextview becomes bigger, its parent view also increase in height?
Start by clearing all your constraints from everything so we have a fresh slate.
Step 1: Build your view hierarchy. In this example, we want something like this:
The view controller's view, which we'll call parentView has a subview, which we'll call redView. That redView has a child, a Text Field, which we'll call textField.
The hierarchy looks like this:
Step 2: Set any constraints that are specific to any individual view. In this case, we probably only want to set a width constraint on our text view. For now, I'll just set a width of 200pts.
Step 3: Set the constraints between textView and its parent, redView. Let's say we want a 10pt border all the way around. Let's add these constraints:
Once we've added these constraints we'll gets some auto layout warnings and errors. For starters, because the constraints I added for with and space to superview don't match the actual sizes, I'll get some warnings like this:
There will also be some errors describing missing X and Y positions for redView and for textView. There are really twice as many errors here as necessary. textView knows where to position itself relative to redView. We don't need more constraints to sort out textView's position. However, redView doesn't know where to position itself yet... and so ultimately, textView also sort of doesn't exactly know.
We can update the textView's frame to get rid of the warnings, but let's go ahead and fix the actual errors.
Step 5: Set up redView's constraints relative to the superView. redView already know what size to be. Notice we had no errors for redView's width. It just doesn't know where to be. In this case, I'll go simple and say we want redView to be centered. So we'll want to add these constraints:
Now we've fixed some of the problems. The only problem that remains is the height for everything.
To fix this, we must set the content sizing priorities of textView. Set these all to 1000 and change the "Intrinsic Size" property to "Placeholder".
By now, all of the auto layout errors should be gone and we should only be left with warnings because our storyboard frames don't match what our constraints say they should.
We can fix that by selecting parentView and updating all the frames:
There's one final caveat to this auto layout puzzle when it comes to autosizing based on content size: what happens if our text view has no content?
If our textview has no content, auto layout will choose a height of 0, and our users won't even be able to see that there's a text view there, much less tap in it to add content (and make it expand). When using auto layout and content-based sizing, we should almost always be sure that we've set either an explicit or minimum size for the content view.
We don't have to worry about our textView's width, as we set this explicitly to 200. So let's add a minimum height constraint. Start by adding any height constraint:
Now go to the size inspector for the textView, find this height constraint we added, and edit it into a greater than or equal to constraint:
Storyboard won't reflect the change in content in our textView and resize it appropriately, but your constraints are now set up correctly and this will behave appropriately on your device or in the simulator.
ON UITextView make your you unselected These
Scrolling Enabled
Bounces
Bounce Horizontally
Bounce Vertically
Shows Horizontal Indicator
Shows vertical indicator
Now Change your auto layout constraints like this.
On the Storyboard Page, click on your textview.
Then click on the small triangular in the lower right corner.
Click first on "Clear Constraints".
An then on "Add Missing Constraints".
Its the easiest way.

Resources