tableHeaderView with Autolayout not working correctly - ios

Hey everybody i have a TableHeaderView and everything gets managed by Autolayout:
The UIImageView at the top should be always 2:1, so i set the Aspect ration and the Rest of the needed Constraints.
The 4 UIButtons should be always horizontal and should have the same Height and Width. So i worked with Equal Width and Equal Height and also with a Aspect Ratio of 1:1
And i have two UILabels with numberOfLines set to 0. I also made a Subclass of my UILabel, because of the preferredMaxLayoutWidth, like this:
- (void) layoutSubviews
{
[super layoutSubviews];
if ( self.numberOfLines == 0 )
{
if ( self.preferredMaxLayoutWidth != self.frame.size.width )
{
self.preferredMaxLayoutWidth = self.frame.size.width;
[self setNeedsUpdateConstraints];
}
}
}
This is my Code:
- (void)initializeHeaderViewLabels
{
//After the Response from my server arrived i set the tableHeaderView with the Textdata
self.tableView.tableHeaderView = nil;
if((self.contentDict[#"title"]) != [NSNull null])
{
self.headerTitleLabel.text = (self.contentDict[#"title"]);
}
if((self.contentDict[#"shortDescription"]) != [NSNull null])
{
self.headerDescriptionLabel.text = (self.contentDict[#"shortDescription"]);
}
[self.headerView setNeedsLayout];
[self.headerView layoutIfNeeded];
CGFloat height = [self.headerView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
CGRect headerFrame = self.headerView.frame;
headerFrame.size.height = height;
self.headerView.frame = headerFrame;
[self.tableView setTableHeaderView:self.headerView];
}
I get my Image and the Text for the UILabels from my Server, so i have to wait until the Response arrives, then i call initializeHeaderViewLabels.
**My Problem is that the tableHeaderView is way too large during Runtime and so my UILabels get stretched and there is a lot of whiteSpace. Maybe i miss something?

In order to make it work you'll need some magic or migrate away from table header view. I've already answered on a similar question here. The trick is to magically reset tableHeaderView after evaluating it's height via autolayout. I've created sample project for that: TableHeaderView+Autolayout.

Try below solution
- (void)sizeHeaderToFit
{
UIView *header = self.tableView.tableHeaderView;
[header setNeedsLayout];
[header layoutIfNeeded];
CGFloat height = [header systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
CGRect frame = header.frame;
frame.size.height = height;
header.frame = frame;
self.tableView.tableHeaderView = header;
}
Source:
table header view height is wrong when using auto layout, IB, and font sizes
Also refer below question...!
How do I set the height of tableHeaderView (UITableView) with autolayout?

My problem was that I was setting constraints on the my header view that were mapping some frame values to superview frame values. When I removed the constraints and just set the frame directly, everything worked.

Header view height is set in the table view delegate. By default it is the same size as in interface builder which is too large when run in app since the width for interface builder is 600.
So what you need is to implement this method in UITableViewDelegate
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 200.0 // Set the desired height based on your device or what ever you are using.
}
And Objective-C version:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 200.0f;
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 200;
}

Related

iOS8 How dynamically fixed UITableViewHeaderFooterView height size?

I use the method as follows
I have just tried below lines of code, dynamically set the UITableViewHeaderFooterView height size.
self.tableView.estimatedSectionHeaderHeight = 100
self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension
I have the following problems
In iOS9, iOS10 can run normally, and can display properly. But can not be displayed correctly in iOS8, and the following error is displayed:
My analysis is as follows:
From the error prompt, I can see that the problem is NSLayoutConstraint: 0x7f8498d7b890 _UITableViewHeaderFooterContentView: 0x7f8498cb9200.height == 0
But I have never made any Constraints to UITableViewHeaderFooterContentView
How should I fit iOS8?
You need to use the UIView systemLayoutSizeFittingSize:
-(void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
[ViewHeader setNeedsLayout];
[ViewHeader layoutIfNeeded];
CGFloat height = [ViewHeader systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
CGRect headerFrame = ViewHeader.frame;
headerFrame.size.height = height;
ViewHeader.frame = headerFrame;
[tbl setTableHeaderView:ViewHeader];
}

contentSize.height returns lesser height in UITableView

I have a tableview inside a scrollview, and I need the tableview to display the entire content, and for which I set the height constraint of the tableview equal to its content size.
self.dealsTableView.estimatedRowHeight = 40;
self.dealsTableView.rowHeight = UITableViewAutomaticDimension;
self.dealsTableView.delegate = self;
self.dealsTableView.dataSource = self;
[self.dealsTableView reloadData];
[self.dealsTableView layoutIfNeeded];
[self.view layoutIfNeeded];
self.dealTableViewHeightConstraint.constant = self.dealsTableView.contentSize.height;
[self.view layoutIfNeeded];
[self.view layoutSubviews];
[self.dealsTableView layoutIfNeeded];
The contentSize.height is always returned less then expected causing the view to break.
If I add a few pixels manually,
self.dealTableViewHeightConstraint.constant = self.dealsTableView.contentSize.height + 50;
It works, but ofcourse, that cannot work in all cases.
Any ideas?
Ok, it was a weird solution, but this is what worked.
The solution is to setup the height constraint before setting the actual content size.
self.dealTableViewHeightConstraint.constant = 40 * self.business.dealArray.count;
self.dealTableViewHeightConstraint.constant = self.dealsTableView.contentSize.height;

UITableViewAutomaticDimension on custom UITableViewCell

I am using UITableViewAutomaticDimension for multiline UILabel in UITableViewCell and everything works fine on iPhone. To add a margin to the table view on iPad I'm using a custom subclass overriding setFrame:
- (void)setFrame:(CGRect)frame {
if (IS_IPAD) {
CGFloat inset = 100;
frame.origin.x += inset;
frame.size.width -= 2 * inset;
}
[super setFrame:frame];
}
The problem is, that the UITableViewAutomaticDimension is returning the wrong (too small) height for the cell on iPad and the label gets cut off. I assume it's returning the height calculated for the full width.
Is there any way to get the table view calculate the right height?
EDIT:
found a quite hacky solution, but this does not work when setting attributedText
- (void)setFrame:(CGRect)frame {
if (IS_IPAD) {
CGFloat inset = 100;
frame.origin.x += inset;
frame.size.width -= 2 * inset;
for (UIView *subview in self.contentView.subviews) {
if ([subview isKindOfClass:[UILabel class]]) {
UILabel *label = (UILabel *)subview;
if (label.numberOfLines == 0) {
label.preferredMaxLayoutWidth = frame.size.width;
}
}
}
}
[super setFrame:frame];
}
If you are doing something like this. Combining technology of Size Classes and Auto-Layout is able to solve the problem in a very easy way. Otherwise, it will require a lot of redrawing and calculation when you want to do that in a manual way. Also, when you are using UITableViewAutomaticDimension, you should go with this way as well because this flag simply indicates that iOS should calculate the cell height automatically via Auto-Layout.

Dynamically size UITableViewCell's height

I have a UITableViewCell with multiple items inside. (Not just a textView so I cant follow this option.) I'm trying to dynamically size it's height based on the content it has inside.
The heights I will be changing, are a UITextView and a UIView. The textView will constantly be changing (at another method, if you'd like, I can post it). And the UIView will change if the user clicks a button:
Here is my code:
- (void)viewDidLoad
{
self.tableView.rowHeight = UITableViewAutomaticDimension;
}
- (IBAction)thisButton:(id)sender
{
CGRect frame = self.myView.frame;
frame.size.height = 50;
frame.size.width = self.myView.frame.size.width;
self.myView.frame = frame;
// update 'myView's constraint
self.viewHeight.constant = self.myView.frame.size.height;
self.tableView.rowHeight = UITableViewAutomaticDimension;
[myTableView reloadData];
}
Problem:
What happens is, when I press the button, the UIView's height gets
updated, but then everything else in the cell gets moved up, and the cell stays the same size.
When the UITextView's height changes, it doesn't pull everything else
down, and the cells height stays the same. Though the textView's
height does change and it just goes over everything else.
Constraints:
On the UITextView I have 3 constraints - 2 on each side, and 1 on top. The UIView has 3 constraints - 2 on each side, and 1 on the bottom.
I then have a constraint connecting the UIView to the textView.
You can dynamically manage UITableViewCell size by calculating a max height of your internal views:
NSArray *array = [[NSArray alloc] initWithArray:#[view1, view2, view3]];
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
__block CGFloat maxHeight;
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
UIView *view = obj;
if (view.bounds.size.height > maxHeight) {
maxHeight = view.bounds.size.height;
}
}];
return maxHeight;
}
Then in the end of your method that changes view's dimensions you must call [self.tableView reloadData]

Setting dynamic UITableViewCell height

I've got a UITableView with two dynamic rows. Each of the rows is a subclass of UITableViewCell and is loaded from nib. As my rows contain dynamic content, I use layoutSubviews to reposition all subviews:
- (void)layoutSubviews
{
[super layoutSubviews];
CGFloat initialHeight = titleLabel.bounds.size.height;
CGSize constraintSize = CGSizeMake(titleLabel.bounds.size.width, MAXFLOAT);
CGSize size = [titleLabel.text sizeWithFont:titleLabel.font constrainedToSize:constraintSize];
CGFloat delta = size.height - initialHeight;
CGRect titleFrame = titleLabel.frame;
titleFrame.size.height += delta;
titleLabel.frame = titleFrame;
locationLabel.frame = CGRectOffset(locationLabel.frame, 0, delta);
dayLabel.frame = CGRectOffset(dayLabel.frame, 0, delta);
timeLabel.frame = CGRectOffset(timeLabel.frame, 0, delta);
}
The problem is that I can't find a way to determine the height in table view delegate's tableView:heightForRowAtIndexPath: method.
The trick is that I load cell from nib, so just after it's loaded titleLabel.bounds.size.width is 300 px (as in nib), not taking into account type of the device (iPhone/iPad) and current orientation, so it seems impossible to calculate the height without conditional checks for orientation and device type. Any ideas?
Your layoutSubviews doesn't resize the cell, so the following should work:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return cell.frame.size.height;
}
If the cell needs to be resized due to the content changing then you can set self.frame = newFrame inside layoutSubviews.
You can also manual cause layoutSubviews to be called by calling setNeedsLayout.

Resources