UIView纵横比混淆了systemLayoutSizeFittingSize [英] UIView aspect ratio confuses systemLayoutSizeFittingSize

查看:2557
本文介绍了UIView纵横比混淆了systemLayoutSizeFittingSize的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧,另一个UITableViewCell动态高度问题,但有点扭曲。
不幸的是我只有在发布时才能跳到iOS 8,否则问题就解决了。需要iOS> = 7.1。



我正在尝试在单元格顶部创建一个包含两个图像的单元格,在它们下面有一个标题标签,下面是一个描述标签。我知道两个顶部图像将是正方形,因此我希望它们具有相同的尺寸并保持方形纵横比,但在屏幕尺寸变化时调整大小(如方向更改或不同设备)。



可能有助于可视化的图像(由于代表无法包括颜色,可视化帮助):
http://i.stack.imgur.com/kOhkl.png



通知在最后一个文本之后的差距,那不应该在那里。



我在以前的应用程序中实现了动态高度:
在UITableView中使用自动布局进行动态单元布局&变量行高度(成功),现在也使用相同的方法。



我使用故事板和编程设置了约束,但没有成功。



但这是踢球者。致电时:

  CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize] .height; 

在:

   - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 

高度值大于读取时的高度:

  cell.contentView.frame 

另一个问题是,如果我删除图像上的宽高比限制并仅将其更改为显式高度约束,则它可以正常工作。 / p>

对于任何愿意帮助的人,我都会组建一个非常简单的示例项目来说明问题:
https://github.com/alefr/DynamicTableCellHeight



设置使用故事板进行约束,还有一个额外的branch:ExplicitHeightConstraint,它只对图像的高度约束更改宽高比约束。



**所以问题是:**
任何人都可以看到限制高度计算的约束有什么问题,或者有人有任何其他建议来获得想要的结果吗? (虽然我想为视图使用自动布局)。



在工作中有很多限制(虽然没有什么真正的花哨)所以我觉得它更容易查看提供的故事板(github链接),而不是在这里明确说明它们。但如果有人幻想我也能做到这一点。估计的高度计算如下所示:

   - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 

//现在不关心内存泄漏:
DynamicTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@dynamicCell];

[self populateCell:cell withContent:self.tableData [indexPath.row]];

//确保已为此单元格设置了约束,因为它可能刚刚从头开始创建。
//假设您在单元格的updateConstraints方法中设置约束,请使用以下行:
[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];

//设置单元格的宽度以匹配表格视图的宽度。这很重要,这样如果单元格的高度取决于它的宽度(由于
//多行UILabels自动换行等),我们将为不同的表视图宽度获得
//正确的单元格高度。我们不需要在 - [tableView:cellForRowAtIndexPath]
//中执行此操作,因为它在表视图中使用单元格时会自动发生。
//另请注意,在某些情况下,单元格的最终宽度可能不是表格视图的宽度,例如,当在表格视图的右侧显示
//部分索引时。您必须考虑缩小的单元格宽度。
cell.bounds = CGRectMake(0.0f,0.0f,CGRectGetWidth(tableView.bounds),CGRectGetHeight(cell.bounds));

//布局传递单元格,它将根据约束计算所有视图的框架。
//(注意你必须在UITableViewCell子类的 - [layoutSubviews]方法
//里面的多行UILabels上设置preferredMaxLayoutWidth,或者在下面2行之前手动执行! )
[cell setNeedsLayout];
[cell layoutIfNeeded];

//获取单元格内容所需的实际高度
CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize] .height;

//所以我们可以读取调试值
CGRect contentFrame = cell.contentView.frame;
CGRect firstImageFrame = cell.firstArtwork.frame;
CGRect secondImageFrame = cell.secondArtwork.frame;
CGRect nameFrame = cell.name.frame;
CGRect numArtworksFrame = cell.numArtworks.frame;

//在高度上添加一个额外的点来计算单元格分隔符,它在单元格的contentView的底部
//和表格视图单元格的底部之间添加。
height + = 1.0f;
返回高度;
}

- (void)populateCell:(DynamicTableViewCell *)cell withContent:(DynamicContent *)content
{
cell.firstArtwork.image = content.firstImage;
cell.secondArtwork.image = content.secondImage;
cell.name.text = content.name;
cell.numArtworks.text = [NSString stringWithFormat:@%@ artwork,content.numImages];
}

谢谢

解决方案

我遇到了同样的情况,解决了它以覆盖给定单元格中的 systemLayoutSizeFittingSize 函数,并将aspectRation约束替换为高度约束。在以下示例中, mediaPlayerAspectRationConstraint 在视图生命周期中添加到视图中, mediaPlayerHeightContraint 将用于确定正确的单元格高度(参见下面的代码)。



所以,我使用了

  CGFloat height = [cell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize] .height; 

而不是 [cell.contentView systemLayoutSizeFittingSize:]

   - (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize {
self.mediaPlayerHeightContraint.constant = CGRectGetHeight( self.experienceMedia.frame);

//让我们用精确的高度约束替换它(解决方法)。

//删除Unable以同时满足约束条件。例外
[self.contentView layoutIfNeeded];

[self.experienceMedia removeConstraint:self.mediaPlayerAspectRationConstraint];
[self.experienceMedia addConstraint:self.mediaPlayerHeightContraint];

[self setNeedsUpdateConstraints];

CGSize res = [self.contentView systemLayoutSizeFittingSize:targetSize];

[self.contentView layoutIfNeeded];

[self.experienceMedia removeConstraint:self.mediaPlayerHeightContraint];
[self.experienceMedia addConstraint:self.mediaPlayerAspectRationConstraint];

[self setNeedsUpdateConstraints];

返回res;
}


Alright, another UITableViewCell dynamic height problem, but with a little twist. Unfortunately I can't jump to iOS 8 only when released, otherwise the problem would be solved. Need iOS >= 7.1.

I'm trying to achieve a cell with two images on the top of the cell, a title label below them and a description label below that. I know the two top images will be square and thus I want them to be of the same size and to keep the square aspect ratio but resize when the screen size varies (like orientation change or different device).

An image that might help with the visualization (can't include because of rep. Nevermind the colors, visualization help): http://i.stack.imgur.com/kOhkl.png

Notice the gap after the last text, that's not supposed to be there.

I implemented dynamic height in previous application according to: Using Auto Layout in UITableView for dynamic cell layouts & variable row heights (with success), and used the same method now as well.

I have setup the constraints using both storyboards and programmatically but with no success.

Here's the kicker though. When calling:

CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

In:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

the height value is way bigger than the height when reading:

cell.contentView.frame

Another issue is that if I remove the aspect ratio constraints on the images and only changes it to an explicit height constraint it works fine.

For anyone willing to help I put together a really simple sample project illustrating the problem: https://github.com/alefr/DynamicTableCellHeight

It's setup to use storyboards for constraints and there's an extra branch: ExplicitHeightConstraint that does nothing but change the aspect ration constraint to a height constraint for the images.

**So the question is: ** Can anyone see anything wrong with the constraints that makes it confuse the height calculations, or do anyone have any alternative suggestions to get the wanted result? (Although I'd like to use auto layout for the views).

There's quite a few constraints in the works (although nothing really fancy) so I think it's easier to look in the provided storyboard (github link) than stating them explicitly here. But if someone fancies that I can do that as well. The estimated height calculations look like:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

// Don't care about memory leaks now:
DynamicTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"dynamicCell"];

[self populateCell:cell withContent:self.tableData[indexPath.row]];

// Make sure the constraints have been set up for this cell, since it may have just been created from scratch.
// Use the following lines, assuming you are setting up constraints from within the cell's updateConstraints method:
[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];

// Set the width of the cell to match the width of the table view. This is important so that we'll get the
// correct cell height for different table view widths if the cell's height depends on its width (due to
// multi-line UILabels word wrapping, etc). We don't need to do this above in -[tableView:cellForRowAtIndexPath]
// because it happens automatically when the cell is used in the table view.
// Also note, the final width of the cell may not be the width of the table view in some cases, for example when a
// section index is displayed along the right side of the table view. You must account for the reduced cell width.
cell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableView.bounds), CGRectGetHeight(cell.bounds));

// Do the layout pass on the cell, which will calculate the frames for all the views based on the constraints.
// (Note that you must set the preferredMaxLayoutWidth on multi-line UILabels inside the -[layoutSubviews] method
// of the UITableViewCell subclass, or do it manually at this point before the below 2 lines!)
[cell setNeedsLayout];
[cell layoutIfNeeded];

// Get the actual height required for the cell's contentView
CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

// So we can read debug values
CGRect contentFrame = cell.contentView.frame;
CGRect firstImageFrame = cell.firstArtwork.frame;
CGRect secondImageFrame = cell.secondArtwork.frame;
CGRect nameFrame = cell.name.frame;
CGRect numArtworksFrame = cell.numArtworks.frame;

// Add an extra point to the height to account for the cell separator, which is added between the bottom
// of the cell's contentView and the bottom of the table view cell.
height += 1.0f;
return height;
}

- (void)populateCell:(DynamicTableViewCell*)cell withContent:(DynamicContent*)content
{
    cell.firstArtwork.image = content.firstImage;
    cell.secondArtwork.image = content.secondImage;
    cell.name.text = content.name;
    cell.numArtworks.text = [NSString stringWithFormat:@"%@ artworks", content.numImages];
}

Thanks

解决方案

I was in the same situation, and solved it to override the systemLayoutSizeFittingSize function in the given cell and replace the aspectRation constraint to a height constraint. In the following example the mediaPlayerAspectRationConstraint is added to the view during the view lifecycle and the mediaPlayerHeightContraint is going to use to determine the right height of the cell (see the code below).

So, I used the

CGFloat height = [cell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

instead of the [cell.contentView systemLayoutSizeFittingSize:].

- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize {
    self.mediaPlayerHeightContraint.constant = CGRectGetHeight(self.experienceMedia.frame);

    //Lets replace it with an exact height constraint (workaround).

    //To remove the Unable to simultaneously satisfy constraints. exceptions
    [self.contentView layoutIfNeeded];

    [self.experienceMedia removeConstraint:self.mediaPlayerAspectRationConstraint];
    [self.experienceMedia addConstraint:self.mediaPlayerHeightContraint];

    [self setNeedsUpdateConstraints];

    CGSize res = [self.contentView systemLayoutSizeFittingSize:targetSize];

    [self.contentView layoutIfNeeded];

    [self.experienceMedia removeConstraint:self.mediaPlayerHeightContraint];
    [self.experienceMedia addConstraint:self.mediaPlayerAspectRationConstraint];

    [self setNeedsUpdateConstraints];

    return res;
}

这篇关于UIView纵横比混淆了systemLayoutSizeFittingSize的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆