我开始欣赏Auto Layout为我所做的工作,但我与布伦特西蒙斯就not using Interface Builder的主题建立了约束。 Apple提供的界面非常灵活,但极其冗长 - 明确设计用于代码生成器而非人类使用。对我而言,它例证了最糟糕的Objective-C,重复了过长的相同前缀,很少使用参数来模糊所有含义,而不是为代码提供清晰度。我见过Florian Kugler's FLKAutoLayout隐藏了UIView
中类别中的约束创建。
还有其他方法可以使代码中的布局约束更清晰,更容易理解吗?
答案 0 :(得分:9)
Masonry是一个用于自动布局的DSL,它比手动创建的线条和布局约束更易读。 通过iOS Dev Weekly。
UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10);
[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(superview.mas_top).with.offset(padding.top);
make.left.equalTo(superview.mas_left).with.offset(padding.left);
make.bottom.equalTo(superview.mas_bottom).with.offset(-padding.bottom);
make.right.equalTo(superview.mas_right).with.offset(-padding.right);
}];
它还具有设置边,大小和中心的复合约束:
// make top, left, bottom, right equal view2
make.edges.equalTo(view2);
// make top = superview.top + 5, left = superview.left + 10,
// bottom = superview.bottom - 15, right = superview.right - 20
make.edges.equalTo(superview).insets(UIEdgeInsetsMake(5, 10, 15, 20))
// make width and height greater than or equal to titleLabel
make.size.greaterThanOrEqualTo(titleLabel)
// make width = superview.width + 100, height = superview.height - 50
make.size.equalTo(superview).sizeOffset(CGSizeMake(100, -50))
// make centerX and centerY = button1
make.center.equalTo(button1)
// make centerX = superview.centerX - 5, centerY = superview.centerY + 10
make.center.equalTo(superview).centerOffset(CGPointMake(-5, 10))
答案 1 :(得分:1)
我尽量保持与Apple的实施尽可能接近,承认存在NSLayoutConstraint
,所以我只是定义了一组 Concise Auto Layout macros 从属性和关系中删除前缀,并将约束创建包装在类似构造函数的宏中(也省略了我从未使用过的乘数参数):
Constraint
ConstantConstraint
VisualConstraints
VisualConstraintWithMetrics
要将多个简单约束附加到视图中,我将它们包装在数组文字中。我总是在非零常数前面加上一个符号,以强调位移。在实践中,它看起来像这样(实例变量对视图有影响):
[self.view addConstraints:
@[Constraint(_verticalSeparator, CenterX, Equal, _top, CenterX, 0),
Constraint(_verticalSeparator, CenterY, Equal, _top, CenterY, +22),
Constraint(_verticalSeparator, Height, Equal, _localWeather, Height, 0),
Constraint(_localWeather, CenterY, Equal, _verticalSeparator, CenterY, 0),
Constraint(_addLocation, CenterY, Equal, _verticalSeparator, CenterY, 0),
Constraint(_touchDown, Trailing, Equal, _verticalSeparator, Trailing, -1),
Constraint(_touchDown, CenterY, Equal, _localWeather, CenterY, 0),
Constraint(_touchDown, Width, Equal, _localWeather, Width, +26),
Constraint(_touchDown, Height, Equal, _localWeather, Height, 0)
]];
id f = @"[_localWeather]-space-[_verticalSeparator]-space-[_addLocation]";
[self.view addConstraints:
VisualConstraintWithMetrics(f, @{@"space": @11},
_localWeather, _verticalSeparator, _addLocation)];
[_tableCell addConstraint:ConstantConstraint(_tableCell, Height, Equal, 44)];
当处理所有共享相同设置的视图组时,我会像这样枚举数组文字:
[@[_top, _middle, _bottom, _touchDown, _verticalSeparator]
enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL *stop) {
view.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:view];
}];
水平地填充superview
经常发生,它被提升到自己的宏:
[@[_top, _middle, _bottom] enumerateObjectsUsingBlock:horizontallyFillSuperview];
随着我的风格发展,我会更新这个答案......
答案 2 :(得分:0)
您也可以使用Parus lib来指定约束。 这个lib的主要思想是不与NSLayoutConstraint本身分开,并允许你根据需要使用约束进行操作。
例如:
[self.view addConstraints:
@[Constraint(_verticalSeparator, CenterX, Equal, _top, CenterX, 0),
Constraint(_verticalSeparator, CenterY, Equal, _top, CenterY, +22),
Constraint(_verticalSeparator, Height, Equal, _localWeather, Height, 0),
Constraint(_localWeather, CenterY, Equal, _verticalSeparator, CenterY, 0),
Constraint(_addLocation, CenterY, Equal, _verticalSeparator, CenterY, 0),
Constraint(_touchDown, Trailing, Equal, _verticalSeparator, Trailing, -1),
Constraint(_touchDown, CenterY, Equal, _localWeather, CenterY, 0),
Constraint(_touchDown, Width, Equal, _localWeather, Width, +26),
Constraint(_touchDown, Height, Equal, _localWeather, Height, 0)
]];
id f = @"[_localWeather]-space-[_verticalSeparator]-space-[_addLocation]";
[self.view addConstraints:
VisualConstraintWithMetrics(f, @{@"space": @11},
_localWeather, _verticalSeparator, _addLocation)];
看起来像:
[self.view addConstraints PVGroup(@[
PVCenterXOf(_verticalSeparator).equalTo.centerXOf(_top),
PVCenterYOf(_verticalSeparator).equalTo.centerYOf(_top).plus(22),
PVHeightOf(_verticalSeparator).equalTo.heightOf(_localWeather),
PVCenterYOf(_localWeather).equalTo.centerYOf(_verticalSeparator),
PVCenterYOf(_addLocation).equalTo.centerYOf(_verticalSeparator),
PVTrailingOf(_touchDown).equalTo.trailingOf(_verticalSeparator).minus(1),
PVCenterYOf(_touchDown).equalTo.centerYOf(_localWeather),
PVWidthOf(_touchDown).equalTo.widthOf(_localWeather).plus(26),
PVHightOf(_touchDown).equalTo.heightOf(_localWeather),
PVVFL("[_localWeather]-space-[_verticalSeparator]-space-[_addLocation]"),
]).withViews(NSDictionaryOfVariableBindings(_localWeather, _verticalSeparator, _addLocation))
.withMetrics(@{@"space": @11}).asArray];
同样Parus可以处理不正确的情况,例如
Constraint(_verticalSeparator, CenterY, Equal, _top, Width, +22)
和其他人。