setNeedsLayout relayouts之后才已经显示单元格 [英] setNeedsLayout relayouts the cell only after is has been displayed

查看:174
本文介绍了setNeedsLayout relayouts之后才已经显示单元格的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有细胞表视图,有时有可选UI元素,有时它必须被除去。
根据不同的元素,标签大小。

I have a table view with cells, which sometimes have an optional UI element, and sometimes it has to be removed. Depending on the element, label is resized.

当细胞被初始化,它是窄于它会稍后。当我设置数据到标签,这code是由一个名为的cellForRowAtIndexPath:

When cell is initialised, it is narrower than it will be later on. When I set data into the label, this code is called from cellForRowAtIndexPath:

if (someFlag) {
    // This causes layout to be invalidated
    [flagIcon removeFromSuperview];
    [cell setNeedsLayout];
}

在此之后,细胞被返回到表图,它显示。然而,在该点的文本标签已经调整了其宽度,但不是高度。高度得到之后的第二调整左右,且加加速度是当所有单元都已经显示清晰可见。

After that, cell is returned to the table view, and it is displayed. However, the text label at that point has adjusted its width, but not height. Height gets adjusted after a second or so, and the jerk is clearly visible when all cells are already displayed.

重要注意事项,这只是初始创建的第一个少数细胞的过程中。一旦他们被重用,一切都很好,因为可选的观点被删除,标签已经正确尺寸形成previous用途。

Important note, this is only during initial creation of the first few cells. Once they are reused, all is fine, as optional view is removed and label is already sized correctly form previous usages.

为什么不是细胞完全重新layouted后 setNeedsLayout ,但已经显示之前呢?不应该显示的UIKit前检查无效的布局?

Why isn't cell re-layouted fully after setNeedsLayout but before it has been displayed? Shouldn't UIKit check invalid layouts before display?

如果我

if (someFlag) {
    [flagIcon removeFromSuperview];
    [cell layoutIfNeeded];
}

都被一次调整,但它似乎是一个不正确的方式来写code,我觉得我失去了别的东西。

all gets adjusted at once, but it seems like an incorrect way to write code, I feel I am missing something else.

如何创建细胞一些较code:

Some more code on how cell is created:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    ProfileCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
    [cell setData:model.items[indexPath.row] forMyself:YES];
    return cell;
}

// And in ProfileCell:
- (void)setData:(Entity *)data forMyself:(BOOL)forMe
{
    self.entity = data;

    [self.problematicLabel setText:data.attributedBody];
    // Set data in other subviews as well

    if (forMe) {
        // This causes layouts to be invalidated, and problematicLabel should resize
        [self.reportButton removeFromSuperview];
        [self layoutIfNeeded];
    }
}

另外,如果它的事项,在故事板细胞看起来像这样,一旦有标志图标被删除可选的约束接管:

Also, if it matters, in storyboard cell looks like this, with optional constraint taking over once flag icon is removed:

推荐答案

我同意,叫 layoutIfNeeded 似乎是错误的,即使它在你的情况。但我怀疑,你失去了一些东西。虽然我没有在表中使用自动布局上做过任何方式的研究,以我的经验细胞的是经过动态布局的是一个有点马车。也就是说,我看到herky生涩布局移除或在运行时添加子视图单元格时。

I agree that calling layoutIfNeeded seems wrong, even though it works in your case. But I doubt that you're missing something. Although I haven't done any research on the manner, in my experience using Auto Layout in table cells that undergo a dynamic layout is a bit buggy. That is, I see herky jerky layouts when removing or adding subviews to cells at runtime.

如果你正在寻找其他的方法(使用自动布局),你可以继承的UITableViewCell 并重写 layoutSubviews 。自定义表格单元格可能它的公共API,可以在的实施设置的tableView在揭露一个标志:的cellForRowAtIndexPath:。细胞的 layoutSubviews 方法将使用标志来确定它是否应该包括可选的UI元素。我不作任何保证,这将消除然而这个问题。

If you're looking for an alternative strategy (using Auto Layout), you could subclass UITableViewCell and override layoutSubviews. The custom table cell could expose a flag in its public API that could be set in the implementation of tableView:cellForRowAtIndexPath:. The cell's layoutSubviews method would use the flag to determine whether or not it should include the optional UI element. I make no guarantees that this will eliminate the problem however.

第二个策略是在来设计两者之间的两个不同的细胞类型和交换的tableView:的cellForRowAtIndexPath:必要

这篇关于setNeedsLayout relayouts之后才已经显示单元格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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