在 Storyboard 中获取子视图的帧
Posted
技术标签:
【中文标题】在 Storyboard 中获取子视图的帧【英文标题】:Getting subViews' frames in Storyboard 【发布时间】:2012-11-15 21:31:11 【问题描述】:我只想(目前)在视图控制器的实例化中获取子视图的尺寸。
[这是我能找到的a previous question 的简单案例。我试图弄清楚为什么 Storyboards 中场景的子视图没有按我预期的方式运行,也就是说:就像 XIB 一样 - 我只想在实际绘制到屏幕之前获取子视图的尺寸]
为了将问题浓缩为一个新的、干净的项目,我这样做:
创建一个新的单视图项目并选中“使用 Storyboard” 将单个 UIView 添加到默认现有MainStoryboard_iPad.storyboard
(并将其背景更改为绿色以使其更容易看到 - 除了缩小一些尺寸之外,这是我对拖到场景中的默认 UIView 所做的唯一更改)
选项-单击导航器中的ViewController.h
文件以将其显示在故事板框架下方的自己的框架中,并在@interface
指令下方插入一对大括号
从 Storyboard 中的 UIView 控制单击并拖动到 ViewController.h
并告诉它命名插座 firstViewFirstSubView
所以我们现在有ViewController.h
:
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
IBOutlet UIView *firstViewFirstSubView;
@end
然后,我将这个方法添加到 ViewController.m:
- (void)viewWillAppear:(BOOL)animated
[super viewWillAppear:animated];
NSLog(@"View Controller will appear. firstViewFirstSubView: %@ ", firstViewFirstSubView);
NSLog(@"subView's dimmensions: %f by %f at %f, %f", firstViewFirstSubView.frame.size.width,
firstViewFirstSubView.frame.size.height,
firstViewFirstSubView.frame.origin.x,
firstViewFirstSubView.frame.origin.y);
此时,我希望能够获得 UIView 子视图的尺寸。不过,我全是 0:
2012-11-15 15:21:00.743 StoryboardViewBounds[11132:c07] View Controller will appear. firstViewFirstSubView: <UIView: 0x9379730; frame = (0 0; 0 0); autoresize = TM+BM; layer = <CALayer: 0x9378e40>>
2012-11-15 15:21:00.744 StoryboardViewBounds[11132:c07] subView's dimmensions: 0.000000 by 0.000000 at 0.000000, 0.000000
我做错了什么?看起来这应该很简单,所以我想我一定错过了一些简单的东西,无论是在 Storyboard 编辑器中抛出正确的开关还是实现 Storyboard 需要的方法。
【问题讨论】:
【参考方案1】:这些维度是在调用layoutSubviews
时计算和设置的,这发生在viewWillAppear
之后。在 UIVIew 上调用 layoutSubviews
后,您可以获得尺寸。
看看在你的视图控制器中实现这个方法:viewDidLayoutSubviews
。此时,您应该能够获得子视图的尺寸。请注意,此调用从 ios 5.0 开始可用,但由于您参考了故事板,我假设您无论如何都在使用故事板或更高版本。
- (void)viewDidLayoutSubviews
[super viewDidLayoutSubviews];
NSLog(@"View Controller did layout subviews. firstViewFirstSubView: %@ ", firstViewFirstSubView);
NSLog(@"subView's dimmensions: %f by %f at %f, %f", firstViewFirstSubView.frame.size.width,
firstViewFirstSubView.frame.size.height,
firstViewFirstSubView.frame.origin.x,
firstViewFirstSubView.frame.origin.y);
【讨论】:
这个成功了,谢谢!我想知道为什么布局文件中初始信息的可用性在我们使用 XIB 文件(以及我使用的所有使用 XIB 文件的教程代码,早在viewDidLoad
)和他们实现 Storyboard 之间发生了变化。无论如何-谢谢!【参考方案2】:
有一个我不得不解决的相关问题,希望可以为其他人节省一天的调试时间:
我在 Storyboard 中发现了这一点:
segue-push
不会导致subView
s 被布置在-viewDidLayoutSubviews
(它们被布置在-viewDidAppear
之前的某个其他时间)。而...
segue-modal
和 [navController.storyboard presentViewController:]
确实 导致 subViews
布局在 -viewDidLayoutSubviews
。
解决方案是将[self.mySubView layoutSubviews]
放在viewController
的-viewDidLayoutSubviews
方法中,以便在mySubView
中手动加载subView
s。
我的情况是我有一个自定义渐变按钮没有正确初始化它的视觉外观。
该按钮包含在 scrollView
中,其中包含 CustomView
,其中包含自定义渐变按钮。
所以,基本上...... scrollView
内的视图中的按钮。
应用程序以 UINavigationController
开始,并加载了其他一些 ViewController1
。ViewController1
包含一个按钮,按下该按钮时,将启动故事板 segue-push
到 @987654341 @.
(这是通过从ViewController1
中的按钮控制拖动到ViewController2
来安排在情节提要中的。
ViewController2
包含scrollview
/customView
/customButton
。
在ViewController2
的-viewDidLayoutSubviews
中,我初始化了customButton
,这是一个自定义渐变按钮,有自己的.h/.m 文件。GradientButton.m
有一个initLayers
以图形方式配置它并需要初始化按钮的 bounds
/frame
属性的方法。但是...
在ViewController2
的-viewDidLayoutSubviews
中,self.customButton
的帧为 0,0,0,0。
几点说明:
-
是的,我在
-viewDidLayoutSubviews
的开头调用[super viewDidLayoutSubviews]
。
在-viewDidLayoutSubviews
布置的唯一视图是self.view
(ViewController2
的初始视图,在 Storyboard 的连接面板中连接。在我的情况下 - self.view
是 scrollView
)。
解决:
-
在
ViewController2
中,我为包含self.customButton
的视图创建了一个出口self.bottomView
。
在ViewController2
的-viewDidLayoutSubviews
,我打电话给[self.bottomView layoutSubviews]
这将导致customButton
的框架/边界被正确设置。
接下来,我调用[self.customButton initLayers]
,它现在可以正确初始化我的自定义渐变按钮。
关于ViewController2
的-viewDidLayoutSubviews:
调用[self.view layoutSubviews]
的一些注意事项导致bottomView
的框架被初始化,但不是customButton
的框架。
在视图层次结构方面,-layoutSubviews
仅适用于 self.view
中的 subView
s,而不适用于 subView
s 中的任何 subView
s。
只有情节提要 segue-push
才会出现这种情况。
情节提要 segue-modal
和程序化的[navController presentViewController]
似乎都正确初始化了视图层次结构的所有级别(subView
s 的所有“subView
s”)到时间@ 987654388@ 被调用。
【讨论】:
非常感谢,遇到完全相同的情况以上是关于在 Storyboard 中获取子视图的帧的主要内容,如果未能解决你的问题,请参考以下文章
Xcode 6 Storyboard 为 UITextView 设置错误的帧大小
ViewController 的子视图的 IBOutlets 在 Storyboard 的 viewDidLoad 中为零