简体   繁体   English

在iOS 7中重新计算旋转时的子视图大小

[英]Recalculating subview sizes on rotation in iOS 7

I have a method I call to calculate the sizes of a bunch of labels I have in a custom UITableViewCell subclass, which is in a UIPopoverController . 我有一个方法,我调用来计算我在自定义UITableViewCell子类中的一堆标签的大小,该子类位于UIPopoverController When the user rotates the device, I need to recalculate the sizes, and then have the table re-drawn to use the new sizes. 当用户旋转设备时,我需要重新计算尺寸,然后重新绘制表格以使用新尺寸。 Every method I've tried to detect the rotation is either depreciated, doesn't get called, or doesn't get called at the right time. 我尝试检测旋转的每个方法都是折旧的,不会被调用,或者在正确的时间没有被调用。 Is there a method that will automatically get called when the device is rotated that I can recalculate my sizes in? 是否有一种方法会在旋转设备时自动调用,我可以重新计算我的尺寸?


Edit: What I have tried and why it doesn't work: 编辑:我尝试了什么,为什么它不起作用:

  • shouldAutorotate - doesn't get called - apparently depreciated. shouldAutorotate - 没有被召唤 - 显然是贬值的。
  • layoutSubviews - gets called, but if I try to [self.tableView reloadData] in here, I get stuck in an infinite loop layoutSubviews - 被调用,但如果我在这里尝试[self.tableView reloadData] ,我会陷入无限循环
  • NSNotificationCenter observer for UIDeviceOrientationDidChangeNotification - Gets called before my controller knows it's new dimensions, so I cannot recalculate my sizes here UIDeviceOrientationDidChangeNotification NSNotificationCenter观察者 - 在我的控制器知道它的新尺寸之前调用,所以我不能在这里重新计算我的尺寸
  • [self.tableView setNeedsDisplay] in layoutSubviews - doesn't prompt re-drawing of table. layoutSubviews [self.tableView setNeedsDisplay] - 不会提示重新绘制表格。
  • didRotateFromInterfaceOrientation - doesn't get called - apparently depreciated. didRotateFromInterfaceOrientation - 没有被调用 - 显然是折旧的。

Edit 2: More details on what I'm trying to do 编辑2:关于我正在尝试做的更多细节

I'm trying to imitate a "rows-and-columns" style table, and line up the labels to imitate the columns. 我正在尝试模仿“行 - 列”样式表,并排列标签以模仿列。 When I recalculate the sizes, I loop through all the rows of the table, then through each "column" in that row. 当我重新计算大小时,我遍历表的所有行,然后遍历该行中的每个“列”。 I get the width of each column, and keep track of the largest width in all the rows for each column. 我得到每列的宽度,并跟踪每列的所有行中的最大宽度。 Then I manipulate the spacing between widths and the font sizes to get it so that if any row has the widest label in every column, it will still fit on the screen. 然后我操纵宽度和字体大小之间的间距来获得它,这样如果任何行在每列中都有最宽的标签,它仍然适合屏幕。

You don't want to rely on the actual rendered UILabels inside of your cell to calculate your "column" widths. 您不希望依赖单元格内部的实际渲染UILabel来计算“列”宽度。 Do this instead: 改为:

  1. Implement a method called calculateColumnWidthsForInterfaceOrientation: that takes an UIInterfaceOrientation . 实现一个名为calculateColumnWidthsForInterfaceOrientation:的方法calculateColumnWidthsForInterfaceOrientation:它接受一个UIInterfaceOrientation In that method, check if the requested orientation is portrait or landscape using UIInterfaceOrientationIsLandscape(orientation) . 在该方法中,使用UIInterfaceOrientationIsLandscape(orientation)检查请求的方向是纵向还是横向。 Then, based on the orientation go through the data you want to display in your labels and find the widest column widths using NSString's sizeWithAttributes: method (or one of its derivatives). 然后,根据方向,浏览要在标签中显示的数据,并使用NSString的sizeWithAttributes:方法(或其衍生产品之一)查找最宽的列宽。 Caches those values in an array or something. 将这些值缓存在数组或其他内容中。
  2. Add a method like setColumnWidths: to your custom table view cell that takes the desired column widths. setColumnWidths:等方法添加到自定义表格视图单元格中,该单元格采用所需的列宽。
  3. In your tableView:cellForRowAtIndexPath: method, retrieve the cached column widths and set it on the cell using the setColumnWidths: method. tableView:cellForRowAtIndexPath:方法中,检索缓存的列宽并使用setColumnWidths:方法在单元格上设置它。
  4. In your cell, layout the labels using the column widths you just set. 在单元格中,使用刚刚设置的列宽布局标签。
  5. In your view controller, implement didRotateFromInterfaceOrientation: . 在视图控制器中,实现didRotateFromInterfaceOrientation: . Inside of it, call calculateColumnWidthsForInterfaceOrientation: with the given orientation and after that call [self.tableView reloadData] . 在其中,调用calculateColumnWidthsForInterfaceOrientation:使用给定的方向,然后调用[self.tableView reloadData]
  6. Finally, in viewDidLoad , call [self calculateColumnWidthsForInterfaceOrientation:self.interfaceOrientation] to do the initial setup of your data before the first rotation. 最后,在viewDidLoad ,调用[self calculateColumnWidthsForInterfaceOrientation:self.interfaceOrientation]在第一次旋转之前进行数据的初始设置。

That should do the trick. 这应该够了吧。

Update: The total width of your cell should be equal to the total width of your table view . 更新: 单元格的总宽度应等于表格视图的总宽度。 That can be managed with auto-layout or by other means. 这可以通过自动布局或其他方式进行管理。 That size will be reflected in the cell's frame size. 该大小将反映在单元格的帧大小中。

Update 2: Since we are talking about a popover , you could maybe simply dismiss the popover in willRotateToInterfaceOrientation:duration: and then display it again with your new desired dimensions after the rotation is done in didRotateFromInterfaceOrientation: . 更新2:由于我们正在谈论一个弹出窗口 ,你可以简单地在willRotateToInterfaceOrientation:duration:willRotateToInterfaceOrientation:duration: ,然后在didRotateFromInterfaceOrientation:完成轮换后再次使用新的所需尺寸显示它didRotateFromInterfaceOrientation:

in layoutSubviews try to recalculate subview one cell 在layoutSubviews中尝试重新计算子视图一个单元格

for example in CustomCell.m 例如在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];

} }

Have you considered using Auto Layout to define your tableView and cells? 您是否考虑过使用自动布局来定义tableView和单元格? Using the proper constraints in conjunction with updateConstraints to update the cell layout upon device rotation should help. 使用适当的约束与updateConstraints一起在设备旋转时更新单元updateConstraints局应该有所帮助。 With this approach you can set the preferredMaxLayoutWidth of each "column's" label and define constraints to handle the appropriate horizontal padding regardless or orientation. 使用此方法,您可以设置每个“列”标签的preferredMaxLayoutWidth ,并定义约束以处理适当的水平填充,无论其方向如何。

Also, if using iOS 7 then you should implement popoverController:willRepositionPopoverToRect:inView: to handle layout of your subviews upon rotation unless you presented the popover from a bar button item. 此外,如果使用iOS 7,那么您应该实现popoverController:willRepositionPopoverToRect:inView:在旋转时处理子视图的布局,除非您从条形按钮项目显示弹出窗口。 I recommend reviewing UIPopoverController Class Reference 我建议您查看UIPopoverController类参考

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM