如何将子视图调整大小传播到超级视图调整大小?

发布于 2024-12-14 14:57:28 字数 1671 浏览 3 评论 0原文

我正在尝试执行与自动调整大小蒙版自动执行的操作相反的操作。那是, 我有一个视图层次结构,我需要将最深的子视图框架中的更改一直传播到链上,以便所有子视图调整大小以适应较新(可能更大)的子视图。

具体来说,我有一个滚动视图,其中有一个子视图作为容器,其中包含一个表,另一个视图又包含一个图像和另一个表。 就像这样:

在此处输入图像描述

这是事件链:

A)

1 最里面的表,有 2 行,如果人名太长,则可能需要向下拉伸(这意味着单元格高度是可变的,并且在运行时在 heightForCellAtIndexPath 上计算)。

2 如果是这样,则需要触发该表和图像的容器视图的拉伸,以便表的单元格最终不会溢出视图。

3 如果是这种情况,则该容器视图下方的另一个表需要向下平移一点以确保它不重叠。请注意,即使步骤 1,2 没有发生,链也可以从这里开始。如果该表的任何 3 行碰巧拉伸以容纳更长的文本,就会出现这种情况。

4 如果上述任何一种情况导致长度增加,则最外层容器视图的长度也需要拉伸。

5 最后,如果此外部容器视图确实拉伸,则根滚动视图需要更改其 contentSize 属性,以便新的更大视图适合并且可以完全滚动(如果大于设备屏幕)。

第一个问题是知道最里面的表何时(在代码中的哪个点)完成布局其单元格以及计算其最终帧。如果我知道最终帧何时已知,我可以将有关 view.frame 更改的 KVO 通知发送到管理所有这些视图的单个视图控制器。但是控制器必须手动调整所有子视图框架的大小。我尝试过这种方法,但框架似乎不准确。我想知道是否存在我没​​有考虑到的时间问题。

例如,这有效:

- (void)viewDidLoad
{
  ...

  [self addObserver:self forKeyPath:@"attendeeContentView.frame" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:NULL];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{
  if([keyPath isEqualToString:@"attendeeContentView.frame"]) 
  {
    CGRect newFrame = [[change objectForKey:NSKeyValueChangeOldKey] CGRectValue];
    UIScrollView *scrollView = (UIScrollView*)self.view;
    scrollView.contentSize = CGSizeMake([[UIScreen mainScreen] applicationFrame].size.width, newFrame.size.height + newFrame.origin.y);
    NSLog(@"\n new contentSize: %f", newFrame.size.height + newFrame.origin.y);
  }
}

但这只是链条中的最后一环。这一切都从最里面的表格扩展以适应所有单元格开始......

有什么想法吗?

I'm trying to do the opposite of what the autoresizing mask automatically does. That is,
I have a view hierarchy and I need to propagate a change in the deepest subview frame all the way up the chain, so that all the subviews resize to fit the newer (possibly bigger) subviews.

Specifically, I have a scroll view that has a a subview as a container, which contains a table, and another view which in turn contains an image and another table.
Like so:

enter image description here

And this is the chain of events:

A)

1 The innermost table, of 2 rows, might have to stretch down if the name of the person is too long (meaning the cell heights are variable and calculated at runtime on heightForCellAtIndexPath).

2 If so, this needs to trigger the stretching of the container view for this table and the image, so that no cells of the table end up overflowing the view.

3 And if that's the case, then the other table below this container view needs to translate down a bit to make sure it's not overlapping. Note that the chain could also start here, even if steps 1,2 don't take place. This would be the case if any this table's 3 rows happens to stretch to accommodate longer text.

4 If any of the above result in an increase in length, the outermost container view needs to stretch in length too.

5 Finally, if this outer container view did stretch, the root scrollview needs to change its contentSize property so that the new bigger view fits and can be fully scrolled if bigger than the device's screen.

The first problem is knowing when (at what point in code) is the innermost table done laying out its cells and its final frame computed. If I knew when is the final frame known, I could send a KVO notification on view.frame change to the single view controller managing all these views. But then the controller would have to manually resize all the subviews frames. I've tried this approach but the frames don't seem accurate. I'm wondering if there might be timing issues I'm not considering.

This works for instance:

- (void)viewDidLoad
{
  ...

  [self addObserver:self forKeyPath:@"attendeeContentView.frame" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:NULL];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{
  if([keyPath isEqualToString:@"attendeeContentView.frame"]) 
  {
    CGRect newFrame = [[change objectForKey:NSKeyValueChangeOldKey] CGRectValue];
    UIScrollView *scrollView = (UIScrollView*)self.view;
    scrollView.contentSize = CGSizeMake([[UIScreen mainScreen] applicationFrame].size.width, newFrame.size.height + newFrame.origin.y);
    NSLog(@"\n new contentSize: %f", newFrame.size.height + newFrame.origin.y);
  }
}

But this is only the final link in the chain. It all starts with the innermost table expanding to fit all cells...

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

东风软 2024-12-21 14:57:28

您只需检查 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 的最后一次调用即可

if (indexPath.row == (NumberOfCells - 1)) {
        // update your views (preferably call it after a slight delay)
}

You can just check for the last call of - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

if (indexPath.row == (NumberOfCells - 1)) {
        // update your views (preferably call it after a slight delay)
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文