UITableView 灵活/动态 heightForRowAtIndexPath [英] UITableView flexible/dynamic heightForRowAtIndexPath

查看:28
本文介绍了UITableView 灵活/动态 heightForRowAtIndexPath的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通常您会使用 cellForRowAtIndexPath 委托方法来设置您的单元格.为单元格设置的信息对于单元格的绘制方式和大小很重要.

Normally you would use the cellForRowAtIndexPath delegate method to setup your cell. The information set for the cell is important for how the cell is drawn and what the size will be.

不幸的是,heightForRowAtIndexPath 委托方法在 cellForRowAtIndexPath 委托方法之前被调用,所以我们不能简单地告诉委托返回单元格的高度,因为这将是那时为零.

Unfortunatly the heightForRowAtIndexPath delegate method is called before the cellForRowAtIndexPath delegate method so we can't simply tell the delegate to return the height of the cell, since this will be zero at that time.

所以我们需要在表格中绘制单元格之前计算大小.幸运的是,有一个方法可以做到这一点,sizeWithFont,它属于 NSString 类.但是有一个问题,为了动态计算正确的大小,它需要知道单元格中的元素将如何呈现.我将在一个例子中说明这一点:

So we need to calculate the size before the cell is drawn in the table. Luckily there is a method that does just that, sizeWithFont, which belongs to the NSString class. However there is problem, in order to calculate the correct size dynamically it needs to know how the elements in the cell will be presented. I will make this clear in an example:

想象一个 UITableViewCell,它包含一个名为 textLabel 的标签.在 cellForRowAtIndexPath 委托方法中,我们放置 textLabel.numberOfLines = 0,它基本上告诉标签它可以有多少行来呈现特定宽度的文本.如果我们给 textLabel 一个大于最初给 textLabel 的宽度的文本,就会出现问题.第二行会出现,但单元格的高度不会自动调整,所以我们会得到一个看起来很乱的表格视图.

Imagine a UITableViewCell, which contains a label named textLabel. Within the cellForRowAtIndexPath delegate method we place textLabel.numberOfLines = 0, which basically tells the label it can have as many lines as it needs to present the text for a specific width. The problem occurs if we give textLabel a text larger then the width originally given to textLabel. The second line will appear, but the height of the cell will not be automatically adjusted and so we get a messed up looking table view.

如前所述,我们可以使用sizeWithFont来计算高度,但是它需要知道使用的是哪种字体,宽度是多少等等.如果为了简单起见,我们只关心宽度,我们可以硬编码宽度约为 320.0(不考虑填充).但是如果我们使用 UITableViewStyleGrouped 而不是普通宽度会发生什么,那么宽度将在 300.0 左右,并且单元格会再次被搞乱.或者如果我们从纵向切换到横向会发生什么,我们有更多的空间,但由于我们硬编码 300.0,它不会被使用.

As said earlier, we can use sizeWithFont to calculate the height, but it needs to know which Font is used, for what width, etc. If, for simplicity reasons, we just care about the width, we could hardcode that the width would be around 320.0 (not taking padding in consideration). But what would happen if we used UITableViewStyleGrouped instead of plain the width would then be around 300.0 and the cell would again be messed up. Or what happends if we swap from portrait to landscape, we have much more space, yet it won't be used since we hardcoded 300.0.

在这种情况下,您有时必须问自己这样一个问题,您可以在多大程度上避免硬编码.

This is the case in which at some point you have to ask yourself the question how much can you avoid hardcoding.

您可以调用属于 UITableView 类的 cellForRowAtIndexPath 方法来获取特定部分和行的单元格.我读了几篇帖子说你不想那样做,但我真的不明白.是的,我同意它已经分配了单元格,但是 heightForRowAtIndexPath 委托方法只为可见的单元格调用,因此无论如何都会分配单元格.如果您正确使用dequeueReusableCellWithIdentifier,单元格将不会在cellForRowAtIndexPath 方法中再次分配,而是使用指针并调整属性.那么有什么问题呢?

You could call the cellForRowAtIndexPath method that belongs to the UITableView class to get the cell for a certain section and row. I read a couple of posts that said you don't want to do that, but I don't really understand that. Yes, I agree it will already allocate the cell, but the heightForRowAtIndexPath delegate method is only called for the cells that will be visible so the cell will be allocated anyway. If you properly use the dequeueReusableCellWithIdentifier the cell will not be allocated again in the cellForRowAtIndexPath method, instead a pointer is used and the properties are just adjusted. Then what's the problem?

请注意,单元格不是在 cellForRowAtIndexPath 委托方法中绘制的,当表格视图单元格变为可见时,脚本将调用 UITableVieCell 上的 setNeedDisplay 方法,从而触发drawRect 方法来绘制单元格.所以直接调用cellForRowAtIndexPath委托不会因为需要绘制两次而损失性能.

Note that the cell is NOT drawn within the cellForRowAtIndexPath delegate method, when the table view cell becomes visible the script will call the setNeedDisplay method on the UITableVieCell which triggers the drawRect method to draw the cell. So calling the cellForRowAtIndexPath delegate directly will not lose performance because it needs to be drawn twice.

好的,通过在 heightForRowAtIndexPath 委托方法中调用 cellForRowAtIndexPath 委托方法,我们会收到我们需要的关于单元格的所有信息,以确定它的大小.

Okay so by calling the cellForRowAtIndexPath delegate method within the heightForRowAtIndexPath delegate method we receive all the information we need about the cell to determine it's size.

也许您可以创建自己的 sizeForCell 方法来运行所有选项,如果单元格是 Value1 样式或 Value2 等会怎样.

Perhaps you can create your own sizeForCell method that runs through all the options, what if the cell is in Value1 style, or Value2, etc.

这只是我在我的想法中描述的一个理论,我想知道我写的是否正确.或者也许有另一种方法可以完成同样的事情.请注意,我希望能够尽可能灵活地做事.

It's just a theory I described in my thoughts, I would like to know if what I wrote is correct. Or that maybe there is another way to accomplish the same thing. Note that I want to be able to do things as flexible as possible.

推荐答案

是的,我同意它已经分配了单元格,但是仅对可见的单元格调用 heightForRowAtIndexPath 委托方法,因此无论如何都会分配单元格.

Yes, I agree it will already allocate the cell, but the heightForRowAtIndexPath delegate method is only called for the cells that will be visible so the cell will be allocated anyway.

这是不正确的.表视图需要为表视图中的所有行调用 heightForRowAtIndexPath(如果已实现),而不仅仅是当前显示的行.原因是它需要计算出它的总高度才能显示正确的滚动指示器.

This is incorrect. The table view needs to call heightForRowAtIndexPath (if it's implemented) for all rows that are in the table view, not just the ones currently being displayed. The reason is that it needs to figure out its total height to display the correct scroll indicators.

这篇关于UITableView 灵活/动态 heightForRowAtIndexPath的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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