【问题标题】:Recalculating subview sizes on rotation in iOS 7在 iOS 7 中重新计算旋转时的子视图大小
【发布时间】:2013-10-25 16:19:33
【问题描述】:

我调用了一个方法来计算我在自定义UITableViewCell 子类中拥有的一堆标签的大小,该子类位于UIPopoverController 中。当用户旋转设备时,我需要重新计算尺寸,然后重新绘制表格以使用新尺寸。我尝试检测旋转的每种方法要么被贬值,要么没有被调用,或者没有在正确的时间被调用。是否有一种方法可以在设备旋转时自动调用,我可以重新计算我的尺寸?


编辑:我尝试了什么以及为什么它不起作用:

  • shouldAutorotate - 没有被调用 - 显然已经贬值了。
  • layoutSubviews - 被调用,但如果我在这里尝试[self.tableView reloadData],我会陷入无限循环
  • NSNotificationCenter UIDeviceOrientationDidChangeNotification 的观察者 - 在我的控制器知道它是新尺寸之前被调用,所以我无法在这里重新计算我的尺寸
  • [self.tableView setNeedsDisplay] in layoutSubviews - 不会提示重新绘制表格。
  • didRotateFromInterfaceOrientation - 没有被调用 - 显然已经贬值了。

编辑 2:有关我正在尝试做的事情的更多详细信息

我正在尝试模仿“行和列”样式表,并排列标签以模仿列。当我重新计算大小时,我会遍历表格的所有行,然后遍历该行中的每个“列”。我得到每列的宽度,并跟踪每列的所有行中的最大宽度。然后我操纵宽度和字体大小之间的间距来获得它,这样如果任何行在每一列中都有最宽的标签,它仍然可以在屏幕上显示。

【问题讨论】:

  • 介意分享你试过哪些方法?不推荐使用 shouldAutorotate。
  • @ChrisH:我可以把它放在那里,但如果我尝试在那里 [self.tableView reloadTable];,我会陷入无限循环。
  • 检查在 UIViewcontroller 中配置视图旋转设置部分以及您尝试过哪些developer.apple.com/library/ios/documentation/uikit/reference/…
  • @KunalBalani 他说他需要调整大小的标签位于自定义单元格中。
  • 似乎使用正确的 autoresizingmask 或 autolayout 可以为您解决这个问题。据我所知,Apple 正试图让我们远离将旋转检测作为布局视图的一种手段。

标签: ios objective-c ios7 uipopovercontroller


【解决方案1】:

您不想依赖单元格内实际呈现的 UILabel 来计算“列”宽度。改为这样做:

  1. 实现一个名为calculateColumnWidthsForInterfaceOrientation: 的方法,该方法采用UIInterfaceOrientation。在该方法中,使用UIInterfaceOrientationIsLandscape(orientation) 检查请求的方向是纵向还是横向。然后,根据方向浏览要在标签中显示的数据,并使用 NSString 的 sizeWithAttributes: 方法(或其派生方法之一)找到最宽的列宽。将这些值缓存在数组或其他东西中。
  2. 将setColumnWidths: 之类的方法添加到采用所需列宽的自定义表格视图单元格中。
  3. 在您的tableView:cellForRowAtIndexPath: 方法中,检索缓存的列宽并使用setColumnWidths: 方法将其设置在单元格上。
  4. 在您的单元格中,使用您刚刚设置的列宽来布局标签。
  5. 在您的视图控制器中,实现didRotateFromInterfaceOrientation:。在其中,使用给定的方向调用calculateColumnWidthsForInterfaceOrientation:,然后调用[self.tableView reloadData]。
  6. 最后,在viewDidLoad 中,调用[self calculateColumnWidthsForInterfaceOrientation:self.interfaceOrientation] 在第一次轮换之前对数据进行初始设置。

这应该可以解决问题。

更新: 单元格的总宽度应等于表格视图的总宽度。这可以通过自动布局或其他方式进行管理。该大小将反映在单元格的框架大小中。

更新 2: 由于我们正在讨论 popover,您可以简单地关闭 willRotateToInterfaceOrientation:duration: 中的弹出框,然后在 didRotateFromInterfaceOrientation: 中完成旋转后以新的所需尺寸再次显示它。

【讨论】:

  • 大部分是我已经在做的。 sizeWithFont: 已被贬值,这就是为什么我需要渲染 UILabels 来计算我的列宽。如何根据方向计算单元格的总宽度(请参阅我对 RahulVyas 对我的 OP 的评论的回复)。另外,didRotateFromInterfaceOrientation 是另一种已被贬值的轮换方法,所以我回到我最初的问题“如何检测轮换”。我会将didRotateFromInterfaceOrientation 添加到我的 OP 中不起作用的列表中。
  • 您对sizeWithFont: 方法的看法是正确的:我已将其更改为sizeWithAttributes:。但是,我不认为 didRotateFromInterfaceOrientation: 已被弃用。我在文档或标题中找不到任何内容。我已经对我的答案添加了另一个更新。
  • 我试过didRotateFromInterfaceOrientation: 并在上面加了一个塞子——它没有被调用(至少在模拟器上——所以也许这是一个仅限模拟器的错误?)。
  • 关于您的更新:我目前正在使用self.tableView.contentSize.width,但这只会返回当前方向的宽度。如果方向发生变化,我将如何提前获得宽度?
  • 旋转时会发生什么?旋转设备时弹出框不会消失并重新出现吗?见stackoverflow.com/questions/3859842/… 和developer.apple.com/library/ios/qa/qa1694/_index.html
【解决方案2】:

在 layoutSubviews 中尝试重新计算子视图一个单元格

例如在 CustomCell.m 中

- (void)layoutSubviews
{

UIViewController *viewController = (id)[(AppDelegate *)[UIApplication sharedApplication].delegate window].rootViewController;

if (UIInterfaceOrientationIsPortrait(viewController.interfaceOrientation))
    self.backgroundColor = [UIColor redColor];
else
    self.backgroundColor = [UIColor greenColor];

}

【讨论】:

  • 嗯,我不认为这与我正在寻找的东西很接近。不过感谢您的尝试。
【解决方案3】:

您是否考虑过使用自动布局来定义您的 tableView 和单元格?结合updateConstraints 使用适当的约束来更新设备旋转时的单元格布局应该会有所帮助。使用这种方法,您可以设置每个“列”标签的preferredMaxLayoutWidth,并定义约束以处理适当的水平填充,无论方向如何。

另外,如果使用 iOS 7,那么您应该实现 popoverController:willRepositionPopoverToRect:inView: 来处理旋转时子视图的布局,除非您从条形按钮项目中呈现弹出框。我建议查看UIPopoverController Class Reference

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多