Is it just me or they added a lot more padding to section headers and footers of grouped UITableViews in iOS 11?
I compiled my app to run with iOS 11 and noticed the extra padding.
I kinda solved it by setting contentInset.top to a negative value checking if the os is iOS 11, but this is a ugly workaround.
Is there any other better way do clear the extra padding of grouped table views in order to achieve the same results across all supported iOS? It kinda stinks to have multiple checks for such a silly thing.
Screenshot for comparison:
As you can see, on iOS 11 there's extra spacing between sections (yeah, those are sections!).
This is new contentInsetAdjustmentBehavior parameter of UIScrollView which you can set it as .never to prevent extra padding
if #available(iOS 11.0, *) {
tableView.contentInsetAdjustmentBehavior = .never
}
or in storyboard under Size Inspector
In iOS 11 the section footer has a view that adds to the spacing between the sections. You would need to set the view of the footer to nil explicitly in addition to adjusting the height for the footer:
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
return nil;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
return 0.1;
}
This will make your table view to look like what you had in iOS 10 and would also not have any effect on previous versions of iOS. You can do the same for the header if you don't need the headers.
You just need to set the table view's header and footer view.
- (UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
return [[UIView alloc] init];
}
- (UIView*)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
return [[UIView alloc] init];
}
I had a similar problem I think it was a bug in the Old Xcode.
If you are using autolayout and you have Content View and views inside this, Constrain to margins didn't work in Xcode 8, now fixed in xCode 9. You have to go in redo your constraints and uncheck the box on the View inside all table view cells. This will then be consistent on all ios 10 and ios 11 devices.
I solved my problem by setting the header and footer height in Storyboard.
Apparently, in Xcode 9 these are the default values when you create a UITableView
I tried to set them to 0, but 1 is the minimum and that solved the problem. Also, I checked how it behaves if the automatic is checked and it works as well.
Also, I don't know is it a bug or something, but I couldn't do it on existing table. I needed to delete it and drag it to UIViewController again.
If rashid's answer didn't work with setting the contentInsetAdjustmentBehavior to never then try the following:
self.tableView.estimatedRowHeight = 0;
self.tableView.estimatedSectionHeaderHeight = 0
self.tableView.estimatedSectionFooterHeight = 0
iOS 11 Floating TableView Header
With my .grouped UITableView I was facing the same issue in iOS 11, it worked fine when I was using a UITableViewController, but not in UIViewController, following worked in my case:
tableView.estimatedSectionHeaderHeight = 0
Without above line tableView(heightForHeaderInSection never gets called.
It seems like a bug in iOS 11.
Related
In my tableView, I am using automatic row & section footer height. It looks good on iOS 10, but on iOS 11 the section footer overlaps the cell on landscape.
Is there some new iOS 11 property that I'm not setting that's causing this?
This is what it looks like running on iOS 10:
This is what it looks like running on iOS 11:
I have xib with a tableView constrained to the edges of the view. I'm setting row/footer/header height in IB:
Do you set your custom heights for header and footer?
Your table view delegate should implement this methods:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
which should return appropriate values.
If you return smaller values then your header and footer views have, then they may overlap.
EDIT
Built a new sample project from scratch and the dynamic tableview cell height is working flawlessly. I then tried to replicate by trimming down my project to it's bare minimum and it's STILL broken (first few cells buggy). Attaching full project for both working and not working examples. Project/code literally looks 99% identical and for the love of me can't figure out where the 1% difference is. The only thing that is popping out at me is that I used different size classes (wAny hAny vs wCompact hRegular but I can't imagine that would do anything given I'm testing in portrait only
Working project:
Not working project:
WORKING (new project from scratch):
https://drive.google.com/file/d/0B_EIkjmOj3ImWXZjVFZMYXZmVGc/view?usp=sharing
NOT WORKING (my project, cleaned up to it's bare minimum)
https://drive.google.com/file/d/0B_EIkjmOj3ImMGRNOXU2RlNkWEk/view?usp=sharing
Have scoured the web trying to understand what is going on, but for some reason my cell heights are incorrect until I scroll past the prototype cells.
Upon initial load:
And after scrolling past each cell:
Background colors:
cell.postTextLabel.backgroundColor = [UIColor orangeColor];
subView.backgroundColor = [UIColor blueColor];
contentView.backgroundColor = [UIColor brownColor];
Not doing anything too fancy here: just a prototype cell, a subview, and three labels (username, timestamp, text).
Below screenshots highlight my constraints in Storyboard:
I pull data from Parse, and am reloading my data while setting tableView layout
[self.tableView setNeedsLayout];
[self.tableView layoutIfNeeded];
[self.tableView reloadData];
And lastly my cellForRowAtIndexPath method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [self postCellAtIndexPath:indexPath];
}
- (UITableViewCell *)postCellAtIndexPath:(NSIndexPath *)indexPath {
static NSString *PostCellIdentifier = #"PostCell";
PostCell *cell = (PostCell *)[self.tableView dequeueReusableCellWithIdentifier:PostCellIdentifier forIndexPath:indexPath];
[self configurePostCell:cell atIndexPath:indexPath];
[cell setNeedsLayout];
[cell layoutIfNeeded];
[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];
return cell;
}
Finally i found the problem why it is not working. I downloaded the Projects which were uploaded to drive by you, and do modifications in it. And found the issue that you use compact Regular size classes which causes error. After converting your size classes to Any, Any it works fine and perfect.so the key of the solution is change wCompact hRegular to wAny hAny. There is no change in code.
That was initial answer.
Detailed Answer :
1) for the size classes first read this document of apple.
2) In your broken demo the size classes are selected as given below :
This indicates that you selected specific view like compact width and regular height means this auto layout will only work in specific iPhone portrait orientation.
Compact Width | Regular Height combination specifies layout changes
that apply only to sizes resembling iPhone devices in portrait
orientation.
The control wCompact hRegular indicates the compact width and regular
height size classes.
I used below size classes and also in your working project i can be able to see below size classes :
In this Size classes it's working fine.
I don't know is it apple's bug or what. !!!
If you want to support only portrait mode and only iPhones then you can choose iPhone in Development Info -> devices. and for orientation you can choose Portrait and upside down in Device orientation.
Hope this helps you to figure out the problem.
I have met the same issue, just try to use a larger estimatedRowHeight which can contain your content. SDK seems do something wrong when using self-sizing cell.
Just set your row height programatically.
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath *)indexPath
{
return rowHieght;
}
for my issue, I set the UILabel font in
layoutSubviews:
thats causing the problem.
after I moved the code to other place, then it works just fine
I also had the same issue,
how-to-add-uiview-in-uitableviewcell
You also have custom cell, so use the following function in customcell class, in your case it is PostCell.m.
- (void)layoutSubviews
{
[super layoutSubviews];
// in my case i only had set frame here while my other
// declarations were in init function, so it solve my problem
}
It solved my same problem, hope it will solve your too, but you have to think it in your own scenario.
First of all you have to set your Detail label line 0 then give leading, trailing and bottom constraints.
in viewDidLoad method add:
tableview.estimatedRowHeight = 50.0 //(your estimated row height)
tableview.rowHeight = UITableViewAutomaticDimension
then return the row height in tableview delegate get method cell row height
In Your code
[cell layoutIfNeeded]
[cell updateContraintsIfNeeded]
are not needed so remove it
In my UIViewController I have dragged a UITableView which has 2 custom Prototype Cells. Basically Its a accordion.
When I am loading data on it there always a gap coming between my table view starting position and first row. when I scroll down Its working fine.I have searched in google and find couple of suggestion like
put
self.automaticallyAdjustsScrollViewInsets = YES;
In viewDidLoad OR add This below code in
UIEdgeInsets insets = UIEdgeInsetsMake(self.topLayoutGuide.length,
0.0,
self.bottomLayoutGuide.length,
0.0);
_detailsTableView.contentInset = insets;
or
YouStoryboard.storyboard > YouViewController > Attributes inspector > Uncheck - Adjust scroll view insets
But none of this worked for me. Here is my UITableView screenshot. Please suggest that how I can remove this gap marked in red.
After fixing this issue UITableView should looks like
Inspector Image 1
Try implementing this method:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
CGFloat height = UITableViewAutomaticDimension;
if (section == 0) {
height = 0.5f;
}
return height;
}
This will remove the spacing for the first section header. If you want to remove all spacings between sections you can always return 0.5f. Such an odd value is needed because Apple does not allow you to return 0 in this method. (That would have the same effect as not implementing the method at all.) But the value 0.5f will have the desired effect.
I think the space you are trying to get rid of is the header. Use the tableview delegate to set the header on section 0 to a height of 0.
tableView:heightForHeaderInSection
There were auto-resizable table view cells introduced in iOS8 (WWDC Session 226 What's new in table and collection views).
In my project I'm trying to implement old fixed rows height behavior. Also, the most important thing for me is to inset default cell.contentView frame with margins on the left and right side.
So, I change the cell.contentView.frame property and immediately after that the -[cell setNeedsLayout] method is being called and and it leads to cell get stuck in an infinite layoutSubviews loop.
Steps to reproduce:
Create new single view project and replace default view controller with the table view controller
Disable table view automatic height calculation
-(void)viewDidLoad {
[super viewDidLoad];
self.tableView.estimatedRowHeight = 0;
self.tableView.rowHeight = 44;
}
3. Drop a custom cell in the table view in storyboard,
Add any subview to the custom cell:,
Subclass the cell and change contentView.frame in layoutSubviews,
Build and run.
Result:
Simulator ends up in a black screen stuck in a infinite layout subviews loop.
Expected Result:
Simulator displaying a table view with a cell's contentView having a custom frame.
Comment:
While debugging a little bit, I found that the infinite loop can be avoided if the cell does not have any custom subviews dropped on it. So it seems the bug will appear after the following conditions are met:
self.tableView.estimatedRowHeight = 0; self.tableView.rowHeight = 44;
cell.contentView.frame = CGRectMake(...)
cell have custom subviews dropped on it in xib or storyboard
Apple does not have the issue in the "Known issues" list for iOS8, so I'm wondering is it actually a bug in iOS8 or does anybody know how to resolve the issue?
This is not a bug: setNeedsLayout will be called any time you change view's frame.
My guess is that changing cell.contentView.frame also changes cell.bounds in iOS 8, triggering relayout. This behavior may be different between iOS versions; anyway, those are standard views, so we shouldn't change them in unsupported ways.
Rather than operating on cell.contentView, how about adding a custom view with insets to it? Or simply creating a height constraint?
In ViewDidLoad please use the below line and there is no need to give the row height
-(void)viewDidLoad {
[super viewDidLoad];
self.tableView.estimatedRowHeight = 44.0f;
self.tableView.rowHeight = UITableViewAutomaticDimension;
}
I have a UITableView in the grouped style, and only one section. However there is some blank space above and below the table view that is shown when the user scrolls too far. How can I remove this blank space?
You can do this by altering the contentInset property that the table view inherits from UIScrollView.
self.tableView.contentInset = UIEdgeInsetsMake(-20, 0, -20, 0);
This will make the top and bottom touch the edge.
Add this code:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 0;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
return 0;
}
Actually this question answered my question.
Reducing the space between sections of the UITableView.
UIView can be inserted at the top and bottom of the table(drag and drop). Set their properties as transparent and height of 1 px. This is to remove the extra padding in front of the cells.
you can also use this code for removing space between first cell of uitableview..
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 0.002f;// set this...
}
Uncheck Extend Edges Under Top bar.
This answer comes quite late, but I hope it helps someone.
The space is there because of the UITableView's tableHeaderView property. When the the tableHeaderView property is nil Apple defaults a view. So the way around this is to create an empty view with a height greater than 0. Setting this overrides the default view thereby removing the unwanted space.
This can be done in a Storyboard by dragging a view to the top of a tableView and then setting the height of the view to a value of 1 or greater.
Or it can be done programmatically with the following code:
Objective-C:
CGRect frame = CGRectZero;
frame.size.height = CGFLOAT_MIN;
[self.tableView setTableHeaderView:[[UIView alloc] initWithFrame:frame]];
Swift:
var frame = CGRect.zero
frame.size.height = .leastNormalMagnitude
tableView.tableHeaderView = UIView(frame: frame)
Comments
As others have noted you can use this same solution for footers.
Sources and Acknowledgements
See the Documentation for more details on the tableHeaderView property.
Thanks to #liushuaikobe for verifying using the least positive normal number works.
My original answer: https://stackoverflow.com/a/22185534/2789144
In my case issue was with the constraints i was applying. I have to change them in order to show 2 rows in my case while bottom of table touching last row.
Use the bounces property of UIScrollView:
[yourTableView setBounces:NO];
This will remove what seems to be an extra padding at the top and bottom of your UITableView.
Actually, it will just disable the tableview's scrollview to scroll past the edge of the content.