UIView for Table View Header Width Wrong - ios

I have a UIView as my tableview header but the width is slightly smaller than the simulator for some reason. I haven't been able to fix this. The tableview is inside of a view controller and the UIView has been allocated like this:
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, self.view.frame.size.width, 40.0)];
The width is showing 375 instead of 400 as it is supposed to be so it is slightly smaller in the iPhone 6 simulator and on my iPhone 6.
I know the width of the iPhone 6 itself is 375, but if you see the view's width in the size inspector it says 400 as you can see in the image below. Also you can see how the UIView is slightly smaller than the UITableView width. This could be due to some spacing issue also, I am not sure. The constraints added to the uitableview were 0 spacing on the top and bottom and -20 on the left and right.

You should set your frame in:
viewDidLayoutSubviews
Because in it frame is correct.

I had a feeling it was the -20 spacing that I had on my tableview. I wasn't sure how to make it 0, but walk_alone suggested unchecking constrain to margins and this allowed me to set the spacing to 0 for both of the side constraints. This allowed for the UIView to take up the full width.

Related

UIScrollView cannot have correct contentSize

I have 4 UIViews in my UIViewController with colours: Yellow, Green, Grey and Blue.
I also gave the following auto layout constraints:
Yellow view: Top-8-superview, Leading-8-superview, Trailing-8-superview, height = 120
Green View: Top-8-YellowView, Leading-8-superview, width=200, height=100
Grey View:Top-8-GreenView, Leading-8-superview, Trailing-8-superview, bottom-8-blueView;
BlueView: Bottom-60-superview, trailing-8-superview, width=260, heigth=30
After compile and run, it looks like this:
At this point, no problem, no constraint complaints, everything is fine.
However, I changed the 4 UIViews' parent view to UIScrollView, and then the UI display wrongly: only green view displays correctly, yellow view and grey view are missing, blue view shows a small part.
In the console I checked that the scrollView's contentSize.width is 16, which is incorrect, so I tried to correct it in viewDidLayoutSubviews:
self.scrollView.contentSize = self.view.bonds.size;
[self.scrollView setNeedsDisplay];
[self.scrollView layoutIfNeeded];
The contentSize becomes (414, 736), which is correct, but the display is still same as my second attached image. I listed out the view details:
YellowView: frame:(8, 28, 0,120)
GreenView: frame:(8, 156, 200,120)
GreyView: frame:(8, 264, 0, 274)
BlueView: frame:(-252, 646, 260,30)
What I observe is, if I give a width constant, the view is at least has width greater than 0, and for the Yellow and Grey view, since they are blank view with no width constrains, they will have problem to show.
What is the best solution to fix it other than give width constraints? I am also wondering why the width of yellow and grey is zero, since I also gave top, leading, trailing, height constraints?
Add contentView as subview of scrollView and then all your subviews as subviews of contentView. Constraints for contentView set as width = superview.width, height >= superview.height and pin 4 sides of contentView to scrollView (leading, top, trailing, bottom). More info: https://www.natashatherobot.com/ios-autolayout-scrollview/

iOS scroll view bounds not equal to superview bounds

I've got a UIScrollView that has constraints pinning it to the superview's leading and trailing edges (not the margins). In this scroll view I have a UIImage which I'm setting to initially be the full width of the scroll view. On the iPhone 7 this works correctly, the image is full width
However on the iPhone 7 Plus there is a gap between the edge of the image and the edge of the screen. The scroll view is full width as when I zoom the image in it does go right to the edge.
I'm getting the image to match the scroll view width by setting
imageView.frame = scrollView.bounds
imageView.contentMode = .scaleAspectFill
The issue seems to be the scroll view bounds. On the iPhone 7 Plus the scroll view width is reported as 375, however the screen width is reported as 414. On the iPhone 7 the scroll view width is 375 and the screen width is also 375.
Anyone know why this is? I'm sure I'm misunderstanding something!
Most probably your problem is that scrollView's frame is not updated yet when you use it to set imageView's frame.
Try to move layout code into viewDidLayoutSubviews instead:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
imageView.frame = scrollView.bounds
}

Springs and struts resizing broken on iOS 8 UITableViewCell

I'm trying to set up a simple UITableViewCell in Interface Builder without auto layout. I'm using the old springs and struts.
When I give a label a flexible width, it seems to lay out as if the UITableViewCell has a much larger width, even though the UITableViewCell tells me it has a width of 375 pixels in layoutSubviews:
- (void)layoutSubviews
{
[super layoutSubviews];
NSLog(#"Label width: %f", self.nameLabel.frame.size.width); // 695.0 for a label that stretches the whole width
NSLog(#"Superview (UITableViewCell) width: %f", self.nameLabel.superview.frame.size.width); // 375.0
}
On a simulated iPhone 5S (iOS 7 or 8), the superview is 320 but the UILabel spreads to 640.
On a simulated iPhone 6, the superview is 375 but the UILabel spreads to 695.
On a simulated iPhone 6 Plus, the superview is 414 but the UILabel speads to 734.
I don't have this problem with other views. For example, I'm able to add a UILabel to a UIViewController and have it stretch the width correctly. What is going on? And how do I fix this?
EDIT:
Interestingly, if I add the constraints programmatically during cellForRowAtIndexPath: then it seems to work as expected, so long as I use the older dequeueReusableCellWithIdentifier instead of dequeueReusableCellWithIdentifier:forIndexPath:. I want to keep all my constraints in Interface Builder though. Any ideas?
I played around a bit with this today. Looks like the frame of the label when it's instantiated relative to the frame of the content view is wrong. If I make the label the same size as the cell in the storyboard, then in awakeFromNib the contentView has a size of CGRectZero but the label has the size I set in the storyboard. Therefore, when you get to layoutSubviews and the contentView is resized to the right size (0,0,320,44), because of the flexible width mask, the label itself is resized along with the content view (width increases by 320 as well). That's why its appearing larger than intended.
The only way I could get around this (albeit, it feels like a gross hack and you should probably stick to auto-layout), was to set the label's frame relative to the content view in awakeFromNib.
- (void)awakeFromNib
{
[super awakeFromNib];
self.label.frame = self.bounds;
}

How to configure view width fixed width and variable height with AutoLayout

I have the following setup: a UIView containing a UILabel and a UIButton. The UIButton has fixed dimensions (it doesn't really matter). The UILabel, however, is constrained by the view's bounds.
I want to be able to set the UIView's width and it should automatically resize itself so that its height allows the whole label content to be visible.
I have tried the following:
self.view.frame = CGRectMake(0, 0, desiredWidth, 0);
CGSize fittingSize = [self.view systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
self.view.frame = CGRectMake(0, 0, fittingSize.width, fittingSize.height);
But this changes both the height and the width of the view, not keeping the width at the desired value.
Is there an elegant method to do this?
Thanks in advance for any help?
In AutoLayout, you would need add a width, top, bottom, leading (left) and/or trailing (right) constraints for the view on to the superview and declare properties for at least the top and/or bottom constraints. After adding the aforementioned constraints you could then change the height of the view by adjusting top and/or bottom constraints constant value.
Here is a link to the Auto Layout Guide.
Auto Layout Guide: Introduction

minimum x-value of the superview’s bounds?

What does this expression "minimum x-value of the superview’s bounds" mean in the Apple Documentation regarding Autolayout in a UIScrollView?
...some notes regarding Auto Layout support for UIScrollView:
In general, Auto Layout considers the top, left, bottom, and right edges of a view to be the visible edges. That is, if you pin a view to
the left edge of its superview, you’re really pinning it to the
minimum x-value of the superview’s bounds. Changing the bounds origin
of the superview does not change the position of the view.
The UIScrollView class scrolls its content by changing the origin of its bounds. To make this work with Auto Layout, the top, left,
bottom, and right edges within a scroll view now mean the edges of its
content view.
1) As I know by default bounds of a view is (0, 0, width, height). So x is 0.
2) How could a view have more x values to take minimum on it?
The Autolayout constraints for any view is generally in relation with the visible bounds of the view but when it comes to a UIScrollView, the Autolayout constraints are in relation with the scrollView's contentView.
Obviously, because a scrollView is, well... supposed to scroll.
Suppose a scrollView has a contentSize of something like:
myScrollView.frame = CGRectMake(0, 0, 100, 100);
myScrollView.contentSize = CGSizeMake(1000, 1000);
now...
Say, in this scrollView you have a subView, something like:
UILabel *lblTest = [UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
[lblTest setText:#"Where am I?"];
[myScrollView addSubView:lblTest];
Before Scrolling:
myScrollView.contentOffset.y will be 0
myScrollView.bounds.y will be 0
myScrollView.frame.origin.y will be 0
lblTest.frame.origin.y will be 0 (and will be visible)
After Scrolling (to bottom):
myScrollView.contentOffset.y will change to 900
myScrollView.bounds.y will also be 900
myScrollView.frame.origin.y will still be 0
lblTest.frame.origin.y will be -900 (and no longer visible)
This is what the Apple Documentation means by:
The UIScrollView class scrolls its content by changing the origin of
its bounds.
Now...
If Autolayout was in relation with the visible bounds of UIScrollView then no matter how much you scrolled, the UILabel would not scroll up.
but...
Since Autolayout in a UIScrollView goes in relation with the scrollView's contentSize, the Autolayout contraints work within it with relation to the scrolling functionality.
So...
When you use Autolayout for subViews in a scrollView, it will be relational to the scrollView's actual size and not the visible size.
apple docs says ask: The UIScrollView class scrolls its content by changing the origin of its bounds.
1) so scrolling can change bounds.x, and than x will be not 0
bounds property is usually (0, 0, width, height), but not always
2) the minimum means: the top, left, bottom, and right edges within a scroll view now mean the edges of its content view.

Resources