Xcode Interface Builder问题
我个人不喜欢界面构建器在Xcode中的工作方式。在这个例子中,我试图创建一个相当复杂的视图控制器。在视图控制器的viewDidLoad
上,我显示了一个自定义警报视图(如此)。它实际上不是一个警报视图,而是一个向用户显示一些信息的视图。我有一个暗淡的背景视图和一个顶部的视图。如果我尝试在界面构建器中创建它,它会变得过于复杂,因为您无法在后台选择视图并移动它们等而不会将子视图丢失到错误的视图中等等...
方案
我想要做的是创建一个视图,其中包含一些标签和一个按钮。视图控制器具有基于此的难度属性,它将在标签/标签数量中具有不同的文本
即简单 - 3个标签
硬 - 4个标签
我创建了dimmedView和alert(样式)视图,如下所示:
// Setup the dimmedView
UIView *dimmedView = [[UIView alloc] initWithFrame:self.view.frame];
dimmedView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.6];
// Setup the startingAlertView
UIView *startingAlertView = [[UIView alloc] init];
startingAlertView.backgroundColor = [UIColor whiteColor];
然后我根据某些逻辑创建三个/四个标签,并根据逻辑将{neossary标签添加到startingAlertView
。
显而易见的问题是,在任何时候都没有设置视图的框架。这意味着它返回0,0,0,0。我想要发生的是根据添加的标签获取所需高度的视图。
我正在为IOS7构建并使用自动布局。我是否应该设置约束,然后调整视图中的相关高度和位置?
答案 0 :(得分:3)
我正在为IOS7构建并使用自动布局。我是否应该设置约束,然后调整视图中的相关高度和位置?
是。您不能在自动布局下使用initWithFrame:
,或者更确切地说,您可以,但框架会被忽略。使用CGRectZero
框架创建调光视图,将translatesAutoresizingMasksToConstraints
设置为NO,将其添加到主视图并创建约束,将其固定到超视图的所有边缘。
然后,再次添加警报视图,框架为零,translates...
属性设置为NO。创建约束以在调光视图中居中此视图。此视图将从其子视图中获取其大小,因为标签具有固有大小。
将标签添加为此视图的子视图,框架为零,translates...
设置为NO。根据其内容,您可能希望设置首选最大布局宽度或宽度约束。
创建约束,将标签固定到超视图的左右边缘,并将标签衬在垂直“堆叠”中。在每种情况下,您都可以添加填充以使警报稍微有点边框。
这可能看起来像是一大堆代码,因此您可能需要阅读我在visual format for auto layout和creating constraints in code上撰写的文章,并使用相关的autolayout convenience category来创建您的生活更轻松。
答案 1 :(得分:0)
如果您要进入自动布局路线,则可以添加约束,以保持每个标签之间的适当空间,以及视图顶部和底部与第一个和最后一个标签之间的适当空间。但是,如果您不在Interface Builder中执行此操作,您也可以跳过使用自动布局,因为在添加标签时调整视图的高度非常简单。
首先,您可以将视图的高度设置为要在标签周围显示的顶部和底部空间的大小。然后每次添加标签时,添加标签的高度加上标签之间的空间高度。
你也可以等到你添加了所需的所有标签,然后将高度设置为底部标签的y位置加上它的高度加上你想要在标签周围的底部空间。
答案 2 :(得分:0)
是的,使用自动布局,您可以从父视图中获取边界。
这是一个快速示例,请注意我们没有使用框架,并且使用CGRectZero作为我们的UILabel,定位来自updateConstraints
。如果您以编程方式执行此操作,我正在使用Visual Format Language来布局我建议的标签。
这里我们将标签设置为父视图的宽度,然后将它们叠加在一起。
#import "View.h"
@implementation View{
UILabel *_label1;
UILabel *_label2;
UILabel *_label3;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
_label1 = [[UILabel alloc] initWithFrame:CGRectZero];
_label1.translatesAutoresizingMaskIntoConstraints = NO;
_label1.text = @"LABEL 1";
_label2 = [[UILabel alloc] initWithFrame:CGRectZero];
_label2.translatesAutoresizingMaskIntoConstraints = NO;
_label2.text = @"LABEL 2";
_label3 = [[UILabel alloc] initWithFrame:CGRectZero];
_label3.translatesAutoresizingMaskIntoConstraints = NO;
_label3.text = @"LABEL 3";
[self addSubview:_label1];
[self addSubview:_label2];
[self addSubview:_label3];
}
[self updateConstraintsIfNeeded];
return self;
}
-(void)updateConstraints
{
[super updateConstraints];
NSDictionary *_viewsDictionary = NSDictionaryOfVariableBindings(_label1,_label2,_label3);
// Set the contraintsto span the entire width of the super view
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_label1]-|"
options:0
metrics:nil
views:_viewsDictionary];
[self addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_label2]-|"
options:0
metrics:nil
views:_viewsDictionary];
[self addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_label3]-|"
options:0
metrics:nil
views:_viewsDictionary];
[self addConstraints:constraints];
// Last setup the vertical contraints other wise they will end up in a random place
constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[_label1]-[_label2]-[_label3]"
options:0
metrics:nil
views:_viewsDictionary];
[self addConstraints:constraints];
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
@end