从 NIB 加载 UIView - 帧大小错误
Posted
技术标签:
【中文标题】从 NIB 加载 UIView - 帧大小错误【英文标题】:Loaded UIView from NIB - Wrong Frame Size 【发布时间】:2013-09-20 05:05:37 【问题描述】:好的,所以我在界面生成器中创建了一个UIView
。我正在使用AutoLayout
,并且我已将此视图的一个子视图固定到所有四个侧面。
这是我不明白的。当我使用loadNibNamed
加载这个NIB 文件时。然后我得到一个对视图的引用。我为这个视图设置了框架。然而,当我访问子视图(使用 [containerView viewWithTag:1
])时,它的框架没有自动调整大小。是什么赋予了?如果您更改父视图的框架,为什么子视图框架不会更改?
这没有任何意义。
为什么你不能只加载一个UIView
,设置它的框架并适当调整所有子视图(特别是因为我使用的是AutoLayout
!)?
编辑:明确地说,我想要做的就是能够在 IB 中定义一个具有适当 AutoLayout
约束的 UIView
层次结构,然后有时能够以不同的大小在屏幕上加载和显示该视图?为什么这么难?
【问题讨论】:
【参考方案1】:当您更改视图的几何图形时,UIKit 不会立即更新子视图几何图形。它会批量更新以提高效率。
运行事件处理程序后,UIKit 会检查屏幕窗口层次结构中是否有任何视图需要布局。如果找到,它会通过解决您的布局约束(如果有)然后发送layoutSubviews
来布置它们。
如果您想解决约束并立即布置视图的子视图,只需向视图发送layoutIfNeeded
:
someView.frame = CGRectMake(0, 0, 200, 300);
[someView layoutIfNeeded];
// The frames of someView.subviews are now up-to-date.
【讨论】:
Rob,您是绅士和学者。谢谢你!你能为我解释一下吗 - 当我创建我的 NIB 时,我定义的所有内容都是项目之间的一组关系。绝对没有硬编码的尺寸。唯一的一个子视图只是固定在父视图的墙上(即父视图和子视图之间的关系,父视图说“无论我变成什么大小,你都会变成”)。所以......真的,当你第一次在代码中加载NIB时,它不应该有一个视图大小,框架的第一个设置应该创建正确的大小?为什么它不能这样工作? 加载 nib 时,视图具有在 nib 中为它们定义的任何大小。当您在代码中更改根视图的大小时,您必须运行布局才能将该更改通过约束传播给子视图。【参考方案2】:我也有同样的问题,我正在创建一个教程视图,我想在其中将多个 UIViews 添加到滚动视图中。当我试图从 xib 获取框架时,它总是给出 320,因此页面的偏移量是错误的,我的视图在 iPhone6 和 6plus 中看起来很糟糕。
然后我使用纯自动布局方法,即不使用框架,而是通过 VFL 添加约束,以便子视图完全适合父视图。下面是我从 Xib 创建大约 20 个 UIView 并正确添加到滚动视图的代码快照
完整代码在这里ScrollViewAutolayout
Method to layout the childviews in the scrollview.
@param nil
@result layout the child views
*/
-(void)layoutViews
NSMutableString *horizontalString = [NSMutableString string];
// Keep the start of the horizontal constraint
[horizontalString appendString:@"H:|"];
for (int i=0; i<viewsArray.count; i++)
// Here I am providing the index of the array as the view name key in the dictionary
[viewsDict setObject:viewsArray[i] forKey:[NSString stringWithFormat:@"v%d",i]];
// Since we are having only one view vertically, then we need to add the constraint now itself. Since we need to have fullscreen, we are giving height equal to the superview.
NSString *verticalString = [NSString stringWithFormat:@"V:|[%@(==parent)]|", [NSString stringWithFormat:@"v%d",i]];
// add the constraint
[contentScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:verticalString options:0 metrics:nil views:viewsDict]];
// Since we need to horizontally arrange, we construct a string, with all the views in array looped and here also we have fullwidth of superview.
[horizontalString appendString:[NSString stringWithFormat:@"[%@(==parent)]", [NSString stringWithFormat:@"v%d",i]]];
// Close the string with the parent
[horizontalString appendString:@"|"];
// apply the constraint
[contentScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:horizontalString options:0 metrics:nil views:viewsDict]];
【讨论】:
【参考方案3】:不幸的是,Rob 接受的答案对我不起作用。这是有效的:
- (id)initWithFrame:(CGRect)frame
self = [super initWithFrame:frame];
if (self)
NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"myXib" owner:self options:nil];
[self addSubview:views[0]];
self.subviews[0].frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height); //ADDED THIS FOR PROPER SIZE
return self;
【讨论】:
以上是关于从 NIB 加载 UIView - 帧大小错误的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Swift 从 UITableViewCell 内的 NIB 调整自定义 UIView 的大小?
如何在加载了 nib 文件的 UIView 中调整子视图的大小