Autolayout Ignores Multi-Line Detailtextlabel When Calculating Uitableviewcell Height (All Styles)

Autolayout ignores multi-line detailTextLabel when calculating UITableViewCell height (all styles)

Further investigations (see UITableViewCellTest) indicate that when UITableViewAutomaticDimension is enabled the system calls -systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority: to calculate the cell height, and that this pretty much ignores the height of the detailTextLabel in its computation (bug !?). As a result, for UITableViewCellStyleSubtitle the cell height is always going to be too short [a single-line detailTextLabel may not quite spill over the cell, but that's only because of the existing top and bottom margins], and for UITableViewCellStyleValue1 or UITableViewCellStyleValue2 the height will be too short whenever the detailTextLabel is taller (eg more lines) than the textLabel. This is all a moot point for UITableViewCellStyleDefault which has no detailTextLabel.

My solution was to subclass and fix with:

- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize
withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority
verticalFittingPriority:(UILayoutPriority)verticalFittingPriority
{
// Bug finally fixed in iOS 11
if ([UIDevice.currentDevice.systemVersion compare:@"11" options:NSNumericSearch] != NSOrderedAscending) {
return [super systemLayoutSizeFittingSize:targetSize
withHorizontalFittingPriority:horizontalFittingPriority
verticalFittingPriority:verticalFittingPriority];
}

[self layoutIfNeeded];
CGSize size = [super systemLayoutSizeFittingSize:targetSize
withHorizontalFittingPriority:horizontalFittingPriority
verticalFittingPriority:verticalFittingPriority];
CGFloat detailHeight = CGRectGetHeight(self.detailTextLabel.frame);
if (detailHeight) { // if no detailTextLabel (eg style = Default) then no adjustment necessary
// Determine UITableViewCellStyle by looking at textLabel vs detailTextLabel layout
if (CGRectGetMinX(self.detailTextLabel.frame) > CGRectGetMinX(self.textLabel.frame)) { // style = Value1 or Value2
CGFloat textHeight = CGRectGetHeight(self.textLabel.frame);
// If detailTextLabel taller than textLabel then add difference to cell height
if (detailHeight > textHeight) size.height += detailHeight - textHeight;
} else { // style = Subtitle, so always add subtitle height
size.height += detailHeight;
}
}
return size;
}

And in the view controller:

- (void)viewDidLoad {
[super viewDidLoad];

self.tableView.estimatedRowHeight = 44.0;
self.tableView.rowHeight = UITableViewAutomaticDimension;
}

You can pull the full subclass from here: MultilineTableViewCell

So far this fix appears to work well, and has let me successfully use the built-in UITableViewCellStyles with multiline text and details, in self-sizing cells with dynamic type support. This avoids the trouble (and mess) of manually computing the desired cell heights in tableView:heightForRowAtIndexPath:, or having to create custom cell layouts.

[(PARTLY)FIXED IN iOS11]

Apple finally fixed this bug in iOS11 (but apparantly only for UITableViewCellStyleSubtitle). I've updated my solution to only apply the necessary correction to pre-11 devices (otherwise you'll end up with extra space top and bottom of your cell!).

Multiline UILabel in a UITableViewCell giving the wrong height with autoLayout in iOS8

Your code is probably correct.i just added this two line (not necessary to say. from the look of your screenshots you already added!)

cell. bodyLabel.numberOfLines = 0;
cell. bodyLabel.lineBreakMode = NSLineBreakByWordWrapping;

Its seems that your problem lay in your user interface. This is the user interface that i used for UITableViewCell and it worked perfectly fine
Sample Image

UPDATE!

just add this to your viewDidLoad [self.view layoutIfNeeded]; [self.view setNeedsLayout];
in viewDidLoad the frame of user interface is being used and you need to update the constraint and view to use the device screen frame The sequence of layoutIfNeeded and setNeedsLayout is important. you need to first call layoutIfNeeded.

UITableViewCell height auto layout not working on iOS 10

This configuration from your viewDidLoad:

tableView.estimatedRowHeight = UITableViewAutomaticDimension
tableView.rowHeight = UITableViewAutomaticDimension

...works only on iOS 11. It is an iOS 11 innovation and does not apply to earlier systems.

For iOS 10, you must supply an actual estimatedRowHeight value (such as 60) to turn on automatic variable row height calculation.

Self-Sizing (Dynamic Height) Cells in iOS 8 - Possible without Custom UITableViewCell?

I just tried this in iOS 10/XCode 8 (same results in iOS 9/XCode 7) with the different cell types and it looks like it's possible ONLY for the textLabel and not for the detailTextLabel.

(basically repeating the issue that the OP mentioned)

ViewController code that sets some text alternately on detailTextLabel and textLabel.

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var tableView: UITableView!

override func viewDidLoad() {
super.viewDidLoad()
tableView.estimatedRowHeight = 44
tableView.rowHeight = UITableViewAutomaticDimension
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
if indexPath.row % 2 == 0 {
cell.textLabel?.text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
cell.detailTextLabel?.text = "<- textLabel"
} else {
cell.textLabel?.text = "detailTextLabel ->"
cell.detailTextLabel?.text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
}
return cell
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}

}

Make sure you set the textLabel and textDetailLabel's line property to 0 and here are the results.

Basic Cell
Sample Image

Right Detail Cell
Sample Image

Left Detail Cell
Sample Image

Subtitle Cell
Sample Image

I'll report this as a bug.

UITableViewAutomaticDimension applied on subtitle table view cell not working properly

Check this Modify code :-

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var cell = tableView.dequeueReusableCellWithIdentifier("Cell")
if (cell == nil)
{

cell = UITableViewCell(style: .Subtitle, reuseIdentifier: "Cell")
cell?.selectionStyle = .None
cell?.detailTextLabel?.font = _SETREGULARFONT_KARLA(IS_IPAD ? 19:15)
cell?.textLabel?.font = _SETBOLDFONT_KARLA(IS_IPAD ? 17:13)
cell?.detailTextLabel?.textColor = getColorFromRGB(120, G: 132, B: 158, A: 1.0)
cell?.detailTextLabel?.numberOfLines = 0
cell?.detailTextLabel?.lineBreakMode = .ByTruncatingTail
cell?.selectionStyle = .None

}

cell?.textLabel?.text = "Testing" + "\(indexPath.row)"
cell?.detailTextLabel?.text = "tesfhjdsfskdfhjkfhdjskfhsjkdfhdjsxdfgfjljkgjfklgfhsdjfhjkdshfdjskfhdjfjkfhafyhdsifjhdjksfbshdjkfkhdksjfhdjsfyhds8ufdhsfjkhdsfjhdfudsiufhdsfh"
cell?.imageView?.image = UIImage(named: "new_temp")

return cell!
}

Please remove the HeightForRowAtIndex datasource Method.

ios8 autolayout: BOTH multi-line(maybe 0 line) label

Cells that are loaded from a storyboard don't start out with the right initial width.

This is why the label isn't sized properly the first time, but appears correctly once you (reload the data, or) scroll the cell off-screen, then on-screen.

Since the cell width is initially incorrect, the label ends up using a preferredMaxLayoutWidth which is wider than the table. (The label thought it had more room to fit everything on one line.)

The solution which worked for me was to make sure my (subclassed) cell's width matched the tableView's width:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];

[cell adjustSizeToMatchWidth:CGRectGetWidth(self.tableView.frame)];

[self configureCell:cell forRowAtIndexPath:indexPath];

[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];

return cell;
}

In TableViewCell.m:

- (void)adjustSizeToMatchWidth:(CGFloat)width
{
// Workaround for visible cells not laid out properly since their layout was
// based on a different (initial) width from the tableView.

CGRect rect = self.frame;
rect.size.width = width;
self.frame = rect;

// Workaround for initial cell height less than auto layout required height.

rect = self.contentView.bounds;
rect.size.height = 99999.0;
rect.size.width = 99999.0;
self.contentView.bounds = rect;
}

I'd also recommend checking out smileyborg's excellent answer about self-sizing cells, along with his sample code. It's what tipped me off to the solution, when I bumped into the same issue you are having.



Related Topics



Leave a reply



Submit