4

我开始欣赏Auto Layout为我所做的工作,但我和 Brent Simmons 一起讨论了不使用 Interface Builder来设置约束的主题。Apple 提供的界面灵活但极其冗长——显然是为代码生成器而不是人类使用而设计的。对我来说,它体现了 Objective-C 最糟糕的一面,重复过长的相同前缀和很少使用的参数混淆了所有含义,而不是使代码更清晰。我见过Florian Kugler 的 FLKAutoLayout,它隐藏了在 category 上的约束创建UIView

还有其他方法可以使代码中的布局约束更清晰、更容易理解吗?

4

3 回答 3

9

Jonas Budelmann 的Masonry是一种用于自动布局的 DSL,它比手动创建的布局约束的行和行更具可读性。通过iOS 开发周刊

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))
于 2013-07-26T14:59:10.173 回答
1

我试图尽可能接近苹果的实现,承认存在NSLayoutConstraint,所以我简单地定义了一组简洁的自动布局宏,它们从属性和关系中删除前缀,并将约束创建包装在一个构造函数类似的宏中(也省略了我从不使用的乘数参数):

  • 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];

随着我风格的发展,我会更新这个答案……</p>

于 2013-07-15T10:12:36.000 回答
0

你也可以使用Parus 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)

和别的。

于 2013-08-21T15:54:27.973 回答