如何使用AutoLayout将UIButtons定位在水平线(包裹,左对齐)?

tho*_*ers 17 xcode interface-builder ios autolayout nslayoutconstraint

我需要在我的应用程序(iOS 6.0及更高版本)中以编程方式创建几个具有各种宽度的UIButton.

我希望以"环绕"样式显示按钮:从左边缘开始,每个按钮应水平放置(按照定义的顺序),如果按钮不适合当前的"线" ,它应该在前一行下面的左边缘开始一个新行.

注意:我不需要表格/网格,因为按钮具有不同的宽度,并且我希望彼此相邻.

布局示例

我可以在我的代码中手动计算每个按钮的框架,但是我应该使用AutoLayout(用编程创建的NSLayoutConstraints)吗?我究竟需要如何设置它?

编辑:在阅读"iOS 6 by Tutorials"的第4章"中间自动布局"后,我不确定使用纯AutoLayout是否可以实现我需要的这种"环绕"功能.

tho*_*ers 8

我当前的解决方案如下所示:没有AutoLayout,但为每种情况手动设置正确的约束(第一个按钮,新行中最左边的按钮,任何其他按钮).

(我的猜测是,直接设置每个按钮的帧将导致代码比使用NSLayoutConstraints更可读)

NSArray *texts = @[ @"A", @"Short", @"Button", @"Longer Button", @"Very Long Button", @"Short", @"More Button", @"Any Key"];

int indexOfLeftmostButtonOnCurrentLine = 0;
NSMutableArray *buttons = [[NSMutableArray alloc] init];
float runningWidth = 0.0f;
float maxWidth = 300.0f;
float horizontalSpaceBetweenButtons = 10.0f;
float verticalSpaceBetweenButtons = 10.0f;

for (int i=0; i<texts.count; i++) {
    UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [button setTitle:[texts objectAtIndex:i] forState:UIControlStateNormal];
    [button sizeToFit];
    button.translatesAutoresizingMaskIntoConstraints = NO;

    [self.view addSubview:button];

    // check if first button or button would exceed maxWidth
    if ((i == 0) || (runningWidth + button.frame.size.width > maxWidth)) {
        // wrap around into next line
        runningWidth = button.frame.size.width;

        if (i== 0) {
            // first button (top left)
            // horizontal position: same as previous leftmost button (on line above)
            NSLayoutConstraint *horizontalConstraint = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0f constant:horizontalSpaceBetweenButtons];
            [self.view addConstraint:horizontalConstraint];

            // vertical position:
            NSLayoutConstraint *verticalConstraint = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop              multiplier:1.0f constant:verticalSpaceBetweenButtons];
            [self.view addConstraint:verticalConstraint];


        } else {
            // put it in new line
            UIButton *previousLeftmostButton = [buttons objectAtIndex:indexOfLeftmostButtonOnCurrentLine];

            // horizontal position: same as previous leftmost button (on line above)
            NSLayoutConstraint *horizontalConstraint = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:previousLeftmostButton attribute:NSLayoutAttributeLeft multiplier:1.0f constant:0.0f];
            [self.view addConstraint:horizontalConstraint];

            // vertical position:
            NSLayoutConstraint *verticalConstraint = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:previousLeftmostButton attribute:NSLayoutAttributeBottom multiplier:1.0f constant:verticalSpaceBetweenButtons];
            [self.view addConstraint:verticalConstraint];

            indexOfLeftmostButtonOnCurrentLine = i;
        }
    } else {
        // put it right from previous buttom
        runningWidth += button.frame.size.width + horizontalSpaceBetweenButtons;

        UIButton *previousButton = [buttons objectAtIndex:(i-1)];

        // horizontal position: right from previous button
        NSLayoutConstraint *horizontalConstraint = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:previousButton attribute:NSLayoutAttributeRight multiplier:1.0f constant:horizontalSpaceBetweenButtons];
        [self.view addConstraint:horizontalConstraint];

        // vertical position same as previous button
        NSLayoutConstraint *verticalConstraint = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:previousButton attribute:NSLayoutAttributeTop multiplier:1.0f constant:0.0f];
        [self.view addConstraint:verticalConstraint];
    }

    [buttons addObject:button];
}
Run Code Online (Sandbox Code Playgroud)

  • 当您使用自动布局时,我会避免直接为视图设置框架. (2认同)

Abi*_*ern 6

您可以使用集合视图,而不是使用Autolayout,您可以使用更好的选项来布置按钮等元素.

它也能够更好地处理旋转下的布局.

  • 谢谢,我没有想过使用CollectionView,但我认为不可能用它来实现这个"Flow/Wrap Around"布局,其中收集项(按钮)都是左对齐的并且距离不同右边缘. (2认同)