自上浆的UITableViewCell中的多个UILabels [英] Multiple UILabels inside a self sizing UITableViewCell

查看:200
本文介绍了自上浆的UITableViewCell中的多个UILabels的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在此的iOS 8应用我创建,我有一个的tableview,我需要他们的自我调整大小。我实现它使用自动布局和它的作品。几乎。下面是它现在的样子。

In this iOS 8 app I'm creating, I have a tableview and I need them to be self resizing. I implemented it using Auto Layout and it works. Almost. Here's how it looks now.

有一个细胞内3标签。其中有Lorem存有文本主要标签。字幕有串号(这是两个不同的标签。可能是困惑,因为它们具有相同的颜色。),然后用黑色小文的第三个标签。

There are 3 labels inside a cell. Main label which has the lorem ipsum text. Subtitle which has the string of numbers (Those are two separate labels. Might be confusing because they have the same color.) Then the third label with the small black text.

第一标签正确地调整本身没有问题和第二标签上下移动相应。但问题是与第三小标签。正如你所看到的,它不是调整自己适合所有文本。

The first label resized itself correctly with no problem and the second label moves up and down accordingly. But the problem is with the third small label. As you can see, its not resizing itself to fit all the text.

现在有一个发生了奇怪的事情。我把它的风景,这里是它。

Now there's a weird thing happening. I turn it landscape and here's it is.

由于有空间的标签显示整个文本它应该。精细。然后,我把它回肖像。

Since there is space the label is displaying the entire text its supposed to. Fine. Then I turn it back to portrait.

现在的小标签已经调整自身以适应其所有的文本,但它溢出的单元格边界。我试图使细胞大,但没有奏效。由于这是自上浆细胞,我不认为这是连的正确方法。

Now the small label has resized itself to fit all its text but it overflows the cells boundaries. I tried making the cell bigger but it didn't work. Since this is self sizing cells, I don't think that's the correct way even.

我没有得到任何错误,甚至无论是在我的自动布局约束警告。

I'm not getting any errors or even warning on my auto layout constraints either.

我在 viewDidLoad中()方法设置code的这两行。

I have set these two lines of code in the viewDidLoad() method.

tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableViewAutomaticDimension

谁能告诉我什么,我可能是错在这里干什么?

Can anyone please tell me what I might be doing wrong here?

由于其很难通过看图片只是回答我没有任何更多的code张贴上面的代码片段旁边,我上传了一个可运行的X code ++项目展示问题的here 。 (有2个定制单元,基本上其相同的细胞只是高度在第二个增加。)

Since its difficult to answer just by looking at images and I don't have any more code to post beside the above snippet, I uploaded a runnable Xcode project demonstrating the issue here. (There are 2 custom cells. Basically its the same cell just the height is increased in the second one.)

我一直在摆弄自动布局约束,但我似乎无法得到这个工作。任何帮助将是AP preciated。

I've been fiddling with auto layout constraints but I can't seem to get this working. Any help would be appreciated.

感谢您。

更新:

有了这个教程的帮助下我发现了一些有益的指针。根据它,每个子视图应该具有约束销其所有侧面和应该有从顶部进入底部,这有助于自动布局来计算小区的高度限制。在我原来的职位,我不得不在每个标签之间的垂直空间,所以我认为这是原因,自动布局无法计算适当的高度。

With the help of this tutorial I found some helpful pointers. According to it, each subview should have constraints that pin all its sides and there should be constraints that goes from top to bottom which helps auto layout to calculate the height of the cell. In my original post, I had vertical spaces between each label so I think that's the reason auto layout couldn't calculate the proper height.

所以,我做了一些改动。

So I made some changes.


  • 我标签之间的垂直空间减小到0,并设置顶部和中部的标签和中部和底部标签之间的垂直空间的限制。

  • 我加了领先,顶部,尾随限制顶端的标签。

  • 开头和结尾中间的标签。

  • 龙头,底部,尾随底部的标签。

现在这里的另一个怪异的一部分。当我第一次运行它,底部标签裁切的问题仍然存在。

Now here's another weird part. When I first run it, the bottom label cropping issue is still there.

但是,如果我旋转设备为横向,然后再将其肖像,所有的所有的细胞都正确调整大小以适应这两个标签!

But if I rotate the device to landscape and turn it back to portrait, all the all the cells are resized properly to fit both labels!

还是想不通,为什么这不会在第一次发生,但。更新了X code ++项目是这里

Still can't figure out why this doesn't happen at first though. Updated Xcode project is here.

推荐答案

这里的问题是多行标签 preferredMaxLayoutWidth 属性。这是告诉标签时,应该自动换行的属性。它必须正确设置每个标签的 intrinsicContentSize 有正确的高度,这是最终什么自动布局将使用以确定细胞的高度。

The issue here is with the multi-line labels' preferredMaxLayoutWidth property. This is the property that tells the label when it should word wrap. It must be set correctly in order for each label's intrinsicContentSize to have the correct height, which is ultimately what Auto Layout will be using to determine the cell's height.

X code 6 Interface Builder中引入了一个新选项,此属性设置为自动的。不幸的是,有一些严重的缺陷(以X code 6.2 / 8.2的iOS的),其中装载从笔尖或故事板细胞时,这是不正确设置/自动。

Xcode 6 Interface Builder introduced a new option to have this property set to Automatic. Unfortunately, there are some serious bugs (as of Xcode 6.2/iOS 8.2) where this is not set correctly/automatically when loading a cell from a nib or Storyboard.

为了解决这个错误,我们需要有 preferredMaxLayoutWidth 一旦显示在设置为正好等于标签的最终宽度表视图。实际上,我们希望从返回小区的tableView之前做到以下几点:的cellForRowAtIndexPath:

In order to work around this bug, we need to have the preferredMaxLayoutWidth set to be exactly equal to the final width of the label once it is displayed in the table view. Effectively, we want to do the following before returning the cell from tableView:cellForRowAtIndexPath::

cell.nameLabel.preferredMaxLayoutWidth = CGRectGetWidth(cell.nameLabel.frame)
cell.idLabel.preferredMaxLayoutWidth = CGRectGetWidth(cell.idLabel.frame)
cell.actionsLabel.preferredMaxLayoutWidth = CGRectGetWidth(cell.actionsLabel.frame)

这是刚刚添加该code不能单独工作的原因是因为当code这3行中执行的tableView:的cellForRowAtIndexPath:,我们在使用每个标签的宽度来设置 preferredMaxLayoutWidth - 但是,如果你在这个时间点检查标签的宽度,标签宽度是完全从它最终会一旦显示单元及其子视图已经奠定了是不同的。

The reason that just adding this code alone doesn't work is because when these 3 lines of code execute in tableView:cellForRowAtIndexPath:, we are using the width of each label to set the preferredMaxLayoutWidth -- however, if you check the width of the labels at this point in time, the label width is totally different from what it will end up being once the cell is displayed and its subviews have been laid out.

我们如何获取标签宽度是准确的在这一点上,让他们反映他们的最终宽度?这里的code,使得它都走到一起:

How do we get the label widths to be accurate at this point, so that they reflect their final width? Here's the code that makes it all come together:

// Inside of tableView:cellForRowAtIndexPath:, after dequeueing the cell

cell.bounds = CGRect(x: 0, y: 0, width: CGRectGetWidth(tableView.bounds), height: 99999)
cell.contentView.bounds = cell.bounds
cell.layoutIfNeeded()

cell.nameLabel.preferredMaxLayoutWidth = CGRectGetWidth(cell.nameLabel.frame)
cell.idLabel.preferredMaxLayoutWidth = CGRectGetWidth(cell.idLabel.frame)
cell.actionsLabel.preferredMaxLayoutWidth = CGRectGetWidth(cell.actionsLabel.frame)

OK,还等什么,我们在这里做什么?那么,你会发现有添加code 3个新品系。首先,我们需要使其表视图的实际宽度相匹配(假设表视图已经铺好并拥有最终宽度,这应该是这种情况)来设置此表格视图单元格的宽度。我们有效地只是让单元格的宽度正确的早期,由于表视图是要最终做到这一点。

OK, so what are we doing here? Well, you'll notice there are 3 new lines of code added. First, we need to set this table view cell's width so that it matches the actual width of the table view (this assumes the table view has already been laid out and has its final width, which should be the case). We're effectively just making the cell width correct early, since the table view is going to do this eventually.

您还会注意到,我们使用 99999 的高度。那是什么呢?这是对这里详细讨论了这个问题一个简单的解决方法,在这里,如果你的约束要求比目前更多的垂直空间该单元格的内容查看的高度,你会得到一个约束的例外实际上并没有表明任何实际问题。细胞或任何其子视图的高度实际上并不重要在这一点上,因为我们只关心获得最终的宽度为每个标签。

You'll also notice that we're using 99999 for the height. What's that about? That is a simple workaround for the problem discussed in detail here, where if your constraints require more vertical space than the current height of the cell's contentView, you get a constraint exception that doesn't actually indicate any real problem. The height of the cell or any of its subviews doesn't actually matter at this point, because we only care about getting the final widths for each label.

接下来,我们确保电池的内容查看具有相同的尺寸,因为我们只分配给细胞本身,通过设置内容查看的边界为等于小区的边界。这是必要的,因为所有你所创建的自动布局约束是相对于内容查看,所以内容查看必须是正确的尺寸,以便他们得到正确解决。只需设置单元格的大小手动做的不可以自动调整大小的内容查看相匹配。

Next, we make sure that the contentView of the cell has the same size as we just assigned to the cell itself, by setting the contentView's bounds to equal the cell's bounds. This is necessary because all of the auto layout constraints you have created are relative to the contentView, so the contentView must be the correct size in order for them to get solved correctly. Just setting the cell's size manually does not automatically size the contentView to match.

最后,我们强迫细胞上布局传递,这将有自动排版引擎解决您的约束和更新所有子视图的帧。由于该单元放大器;内容查看,现在有同样的宽度,他们将在表格视图运行时,标签宽度也将是正确的,这意味着 preferredMaxLayoutWidth 设置为每个标签会准确,会导致标签在正确的时间,这当然意味着标签的高度将被设置正确时,细胞的表视图用于包装!

Finally, we force a layout pass on the cell, which will have the auto layout engine solve your constraints and update the frames of all the subviews. Since the cell & contentView now have the same widths they will at runtime in the table view, the label widths will also be correct, which means that the preferredMaxLayoutWidth set to each label will be accurate and will cause the label to wrap at the right time, which of course means the labels' heights will be set correctly when the cell is used in the table view!

这绝对是UIKit中苹果的错误,我们现在要解决的(所以请不要提交错误报告与苹果,以便他们优先考虑一个修正!)。

This is definitely an Apple bug in UIKit that we have to workaround for now (so please do file bug reports with Apple so they prioritize a fix!).

最后一点:此解决方法会遇到麻烦,如果你的表视图单元格的内容查看宽度不扩展表视图的整个宽度,例如当有一节索引表示在右边。在这种情况下,你需要确保设置单元格的宽度,当您手动考虑到这一点 - 你可能需要硬code这些价值,是这样的:

One final note: this workaround will run into trouble if your table view cell's contentView width doesn't extend the full width of the table view, for example when there is a section index showing on the right. In this case, you'll need to make sure that you manually take this into account when setting the width of the cell -- you may need to hardcode these values, something like:

let cellWidth = CGRectGetWidth(tableView.bounds) - kTableViewSectionIndexWidth
cell.bounds = CGRect(x: 0, y: 0, width: cellWidth, height: 99999)

这篇关于自上浆的UITableViewCell中的多个UILabels的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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