自动布局让我的生活很困难。从理论上讲,当我转换的时候,它会非常有用,但我似乎一直在与它作斗争。
我做了一个演示项目来寻求帮助。有人知道如何使视图之间的空间增加或减少均匀,每当视图调整大小?
下面是三个标签(手动垂直对齐):
我想要的是,当我旋转时,它们均匀地调整间距(而不是视图大小)。默认情况下,顶部和底部视图向中心挤压:
自动布局让我的生活很困难。从理论上讲,当我转换的时候,它会非常有用,但我似乎一直在与它作斗争。
我做了一个演示项目来寻求帮助。有人知道如何使视图之间的空间增加或减少均匀,每当视图调整大小?
下面是三个标签(手动垂直对齐):
我想要的是,当我旋转时,它们均匀地调整间距(而不是视图大小)。默认情况下,顶部和底部视图向中心挤压:
当前回答
对于标签,这至少是可行的:
@“H: | -15 -(第一(第二)= =]-[二(= =第三)](第三(= =))-15 - |
如果第一个和第二个有相同的宽度,第二个和第三个有相同的宽度,第三个和第一个有相同的宽度……你可以做水平(H)和垂直(V)。
其他回答
许多答案是不正确的,但得到许多计数。这里我只是编写了一个解决方案,三个视图是水平对齐的,不使用间隔视图,但它只在标签宽度已知的情况下工作,当在故事板中使用。
NSDictionary *views = NSDictionaryOfVariableBindings(_redView, _yellowView, _blueView);
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|->=0-[_redView(40)]->=0-[_yellowView(40)]->=0-[_blueView(40)]->=0-|" options:NSLayoutFormatAlignAllTop | NSLayoutFormatAlignAllBottom metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_redView(60)]" options:0 metrics:nil views:views]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:_redView attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:_yellowView attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:_redView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:_yellowView attribute:NSLayoutAttributeLeading multiplier:0.5 constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:_blueView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:_yellowView attribute:NSLayoutAttributeLeading multiplier:1.5 constant:40]];
这里还有另一个答案。我在回答一个类似的问题时看到了这个问题的链接。我没有看到任何与我类似的答案。所以我想写在这里。
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.whiteColor()
setupViews()
}
var constraints: [NSLayoutConstraint] = []
func setupViews() {
let container1 = createButtonContainer(withButtonTitle: "Button 1")
let container2 = createButtonContainer(withButtonTitle: "Button 2")
let container3 = createButtonContainer(withButtonTitle: "Button 3")
let container4 = createButtonContainer(withButtonTitle: "Button 4")
view.addSubview(container1)
view.addSubview(container2)
view.addSubview(container3)
view.addSubview(container4)
[
// left right alignment
container1.leftAnchor.constraintEqualToAnchor(view.leftAnchor, constant: 20),
container1.rightAnchor.constraintEqualToAnchor(view.rightAnchor, constant: -20),
container2.leftAnchor.constraintEqualToAnchor(container1.leftAnchor),
container2.rightAnchor.constraintEqualToAnchor(container1.rightAnchor),
container3.leftAnchor.constraintEqualToAnchor(container1.leftAnchor),
container3.rightAnchor.constraintEqualToAnchor(container1.rightAnchor),
container4.leftAnchor.constraintEqualToAnchor(container1.leftAnchor),
container4.rightAnchor.constraintEqualToAnchor(container1.rightAnchor),
// place containers one after another vertically
container1.topAnchor.constraintEqualToAnchor(view.topAnchor),
container2.topAnchor.constraintEqualToAnchor(container1.bottomAnchor),
container3.topAnchor.constraintEqualToAnchor(container2.bottomAnchor),
container4.topAnchor.constraintEqualToAnchor(container3.bottomAnchor),
container4.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor),
// container height constraints
container2.heightAnchor.constraintEqualToAnchor(container1.heightAnchor),
container3.heightAnchor.constraintEqualToAnchor(container1.heightAnchor),
container4.heightAnchor.constraintEqualToAnchor(container1.heightAnchor)
]
.forEach { $0.active = true }
}
func createButtonContainer(withButtonTitle title: String) -> UIView {
let view = UIView(frame: .zero)
view.translatesAutoresizingMaskIntoConstraints = false
let button = UIButton(type: .System)
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle(title, forState: .Normal)
view.addSubview(button)
[button.centerYAnchor.constraintEqualToAnchor(view.centerYAnchor),
button.leftAnchor.constraintEqualToAnchor(view.leftAnchor),
button.rightAnchor.constraintEqualToAnchor(view.rightAnchor)].forEach { $0.active = true }
return view
}
}
同样,这也可以用iOS9 UIStackViews很容易做到。
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.greenColor()
setupViews()
}
var constraints: [NSLayoutConstraint] = []
func setupViews() {
let container1 = createButtonContainer(withButtonTitle: "Button 1")
let container2 = createButtonContainer(withButtonTitle: "Button 2")
let container3 = createButtonContainer(withButtonTitle: "Button 3")
let container4 = createButtonContainer(withButtonTitle: "Button 4")
let stackView = UIStackView(arrangedSubviews: [container1, container2, container3, container4])
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .Vertical
stackView.distribution = .FillEqually
view.addSubview(stackView)
[stackView.topAnchor.constraintEqualToAnchor(view.topAnchor),
stackView.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor),
stackView.leftAnchor.constraintEqualToAnchor(view.leftAnchor, constant: 20),
stackView.rightAnchor.constraintEqualToAnchor(view.rightAnchor, constant: -20)].forEach { $0.active = true }
}
func createButtonContainer(withButtonTitle title: String) -> UIView {
let button = UIButton(type: .Custom)
button.translatesAutoresizingMaskIntoConstraints = false
button.backgroundColor = UIColor.redColor()
button.setTitleColor(UIColor.whiteColor(), forState: .Normal)
button.setTitle(title, forState: .Normal)
let buttonContainer = UIStackView(arrangedSubviews: [button])
buttonContainer.distribution = .EqualCentering
buttonContainer.alignment = .Center
buttonContainer.translatesAutoresizingMaskIntoConstraints = false
return buttonContainer
}
}
注意,这与上面的方法完全相同。它添加了四个容器视图,这些视图都是均等填充的,每个堆栈视图都添加了一个视图,并在中间对齐。但是,这个版本的UIStackView减少了一些代码,看起来不错。
我一直在坐过山车,爱自动布局和讨厌它。喜欢它的关键似乎是接受以下几点:
接口构建器的编辑和“有帮助的”自动创建约束在大多数情况下几乎无用 创建类别来简化常见操作是一种拯救,因为代码是如此重复和冗长。
也就是说,你正在尝试的不是直接的,在接口构建器中很难实现。这在代码中很简单。这段代码,在viewDidLoad,创建和定位三个标签,你需要他们:
// Create three labels, turning off the default constraints applied to views created in code
UILabel *label1 = [UILabel new];
label1.translatesAutoresizingMaskIntoConstraints = NO;
label1.text = @"Label 1";
UILabel *label2 = [UILabel new];
label2.translatesAutoresizingMaskIntoConstraints = NO;
label2.text = @"Label 2";
UILabel *label3 = [UILabel new];
label3.translatesAutoresizingMaskIntoConstraints = NO;
label3.text = @"Label 3";
// Add them all to the view
[self.view addSubview:label1];
[self.view addSubview:label2];
[self.view addSubview:label3];
// Center them all horizontally
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:label1 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:label2 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:label3 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]];
// Center the middle one vertically
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:label2 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0]];
// Position the top one half way up
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:label1 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:label2 attribute:NSLayoutAttributeCenterY multiplier:0.5 constant:0]];
// Position the bottom one half way down
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:label3 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:label2 attribute:NSLayoutAttributeCenterY multiplier:1.5 constant:0]];
我说过,这段代码通过UIView中的一些类别方法简化了很多,但为了清晰起见,这里我做了很多。
对于感兴趣的人来说,这个类别在这里,它有一个方法,可以沿着特定的轴均匀地间隔一个视图数组。
我想水平对齐5张图片,所以我最终遵循了Mete的反应,但有一点不同。
第一个图像将在容器中水平居中,容器的值为0,乘数为1:5:
第二张图片将在容器中水平居中,容器的值为0,乘数为3:5:
其余的图像也是这样。例如,第五张(也是最后一张)图像将在容器中水平居中,容器值为0,乘数为9:5:
正如梅特所解释的,顺序是1,3,5,7,9,等等。位置遵循相同的逻辑:第一个位置是1,然后是空格,然后是下一个位置3,依此类推。
在iOS 9中,苹果通过(期待已久的)UIStackView使这变得非常容易。只需选择要包含在接口构建器中的视图,并选择编辑器->嵌入->堆栈视图。为堆栈视图设置适当的宽度/高度/边距约束,并确保将Distribution属性设置为'Equal spacing':
当然,如果你需要支持iOS 8或更低版本,你必须从其他选项中选择一个。