Dynamic height of UITableViewCell in iOS 7 and iOS 8 not possible

I am having a hard time trying to get a table view with dynamically sized cells that should be laid out well under iOS 7 and 8. I cannot detail all the differences to be found (in "paths" from broken layouts "ways) between iOS 7 and 8. which can be created using various "tweaks", "workarounds" and whatever I've found here and elsewhere.But eventually either on iOS 7 or iOS 8 (if not both) some or all of the content the cell is displaced because the layout system breaks one of the custom "restore" constraints.

Basically I have three different types of content. And since I'm not only displaying this content in the above table view, I've wrapped the content in three subclasses UIView

. Let's call them SummaryView

s For the table view, I created three subclasses UITableViewCell

, each of which adds a corresponding one SummaryView

to it contentView

and sets it self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight

. On updateViewConstraints

I generally delete all "my" limit, which could be added before and ...

- (void)updateConstraints
{
   // ...removed custom constraints before
    NSDictionary *views = NSDictionaryOfVariableBindings(_summaryView);

    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_summaryView]-|"
                                                                       options:0
                                                                       metrics:nil
                                                                         views:views]
                        toView:self.contentView];

    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[_summaryView]-|"
                                                                       options:0
                                                                       metrics:nil
                                                                         views:views]
                        toView:self.contentView];
    [super updateConstraints];
}

      

As tableView:estimatedHeightForRowAtIndexPath:

I return a static estimate, depending on the type of content. In tableView:heightForRowAtIndexPath:

I am using cells "prototype" ok ...

// ..set content on prototype cell before
[prototypeCell setNeedsUpdateConstraints];
[prototypeCell layoutIfNeeded];
CGSize size = [prototypeCell systemLayoutSizeFittingSize:UILayoutFittingExpandedSize];
return size.height;

      

Here, usually the debugger breaks into UIViewAlertForUnsatisfiableConstraints

(on [prototypeCell layoutIfNeeded]

) s <NSLayoutConstraint:0x17409f180 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x17019f070(44)]>

, which conflicts with other restrictions.

So I tried ...

  • Setting up tableView.rowHeight = UITableViewAutomaticDimension

    as a tableviewDidLoad

  • Not performed tableView:estimatedHeightForRowAtIndexPath:

  • Through...

    if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1) {
        cell.contentView.frame = cell.bounds;
        cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
    }
    
          

    ... before applying the contents of the cell and calculating its layout

  • Execution self.contentView.bounds = CGRectMake(0.0, 0.0, 1000, 1000);

    on cell initialization
  • Perhaps other things that I can't remember right now as I've been in this for more than two days.

It's always the same thing, if I reach an option that doesn't complain about unsatisfactory limitations, the layout tends to get messed up. And while I see that the table view does not set a constraint by default <NSLayoutConstraint:0x17409f180 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x17019f070(44)]>

, the constraint that is set (on the height returned tableView:heightForRowAtIndexPath:

) instead is not appropriate for the layout system.

This post is a last resort. I know that without the constraints of specific class classes, you cannot re-check them. But since I can use these views outside of the table view without issue, this shouldn't be a view constraint issue.

I think I'll come back to calculate the sizes of all view elements manually (based on [UIScreen mainScreen].bounds

) and set them directly (like widths and heights) for all subviews. So I can get the specific cell height and set the frame contentView

manually. It's a shame as he notices the layout code wonderfully ....

Regards, Gabriel

+3


source to share


2 answers


In the end I found an acceptable solution that didn't mess up the layout code. Shortly speaking:

In the table cell, updateConstraints

I removed the constraint with _summaryView

-bottom to look down. This way, the height constraints in the content view do not interfere with the topics in the final view.

- (void)updateConstraints
{
    NSDictionary *views = NSDictionaryOfVariableBindings(_summaryView);

    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_summaryView]-|"
                                                                       options:0
                                                                       metrics:nil
                                                                         views:views]
                        toView:self.contentView];

    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[_summaryView]"
                                                                       options:0
                                                                       metrics:nil
                                                                         views:views]
                        toView:self.contentView];
    [super updateConstraints];
}

      

In tableView:heightForRowAtIndexPath:

I just use intrinsicContentSize

for the cell in question to get the height:

        [prototypeCell.summaryView applyStuff];
        [prototypeCell layoutIfNeeded];
        height = [prototypeCell intrinsicContentSize].height;

      



The implementation of the intrinsicContentSize

specified table cell looks like this:

- (CGSize)intrinsicContentSize
{
    // Calculate the available content width if not done yet
    static CGFloat availableWidth = 0.0;
    if (availableWidth == 0.0) {
        availableWidth = CGRectGetWidth([UIScreen mainScreen].bounds);
    }

    // Check if the contentView frame needs an update
    if (CGRectGetWidth(self.contentView.frame) != availableWidth) {
        CGRect frame = CGRectMake(0.0, 0.0, availableWidth, 100.0);
        self.contentView.frame = frame;
    }

    [_summaryView layoutIfNeeded];
    CGSize size = _summaryView.frame.size;
    size.height += 2.0 * V_PADDING;
    size.width += 2.0 * H_PADDING;
    return size;
}

      

Note that for apps that support portrait and landscape mode availableWidth

, this should be reset when the orientation is changed, or shouldn't static

. * _PADDING

is the space that I want to _summaryView

have from all sides.

Next, I removed self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth

from the cell initialization code. As it has no discernible effect.

+2


source


I might be a little late in the discussion, but I had a similar problem and found a solution.

When adding constraints, add them to the contentView, not to the cell. Otherwise, "| -" and "- |" in a visual language format will create restrictions related to the cell itself, and our bad content content will not have any restrictions.



So [self addConstraints: ...];

use instead [self.contentView addConstraints: ...];

.

0


source







All Articles