iOS:使用NSLayoutConstraint将对象堆叠在一起

时间:2013-12-20 18:16:31

标签: ios uibutton nslayoutconstraint

我希望将几个按钮叠放在一起,然后显示/隐藏它们作为切换的方式。 (想想视频播放器中的播放/暂停/重播按钮)。

是否可以使用NSLayoutConstraint执行此操作?

或许,或许还有更好的方法可以在iOS中创建多状态按钮?

这是我尝试过的,但是当它们将它们放在一起时,它们似乎并不起作用:

NSArray *constraints = [NSLayoutConstraint
  constraintsWithVisualFormat:@"|[_playButton][_pauseButton][_replayButton][_scrubber][_minimizeButton]|"
                      options:0
                      metrics:nil
                      views:viewsDictionary];

使用以下@dasdom的一些提示,我已经提出以下建议:

NSArray *constraints = [NSLayoutConstraint
  constraintsWithVisualFormat:@"|[_pauseButton]-[_scrubber]-[_minimizeButton]|"
                      options:NSLayoutFormatAlignAllCenterY
                      metrics:nil
                      views:viewsDictionary];

[constraints arrayByAddingObjectsFromArray:[NSLayoutConstraint
  constraintsWithVisualFormat:@"|[_playButton]"
                      options:NSLayoutFormatAlignAllCenterY
                      metrics:nil
                      views:viewsDictionary]];

[constraints arrayByAddingObjectsFromArray:[NSLayoutConstraint
  constraintsWithVisualFormat:@"|[_replayButton]"
                      options:NSLayoutFormatAlignAllCenterY
                      metrics:nil
                        views:viewsDictionary]];

[self addConstraints:constraints];

哪个非常接近 - 水平间距是正确的,对于第一个规则中的项目(pauseButton,scrubber,最小化),它们垂直对齐,但播放和重放按钮太高......好像后续NSLayoutFormatAlignAllCenterY被忽略。

Edit2:这是我最终得到的最终代码,比我想象的要多得多,但似乎效果很好:

NSDictionary *metrics = @{
    @"buttonPadding": @(kBarPaddingX)
};
// Align along Y center and set order, so scrubber stretches in the middle.
NSString *controlsVisualFormat =
  @"|-buttonPadding-[_playButton]-[_scrubber]-[_minimizeButton]-buttonPadding-|";
NSArray *constraints = [NSLayoutConstraint
  constraintsWithVisualFormat:controlsVisualFormat
                      options:NSLayoutFormatAlignAllCenterY
                      metrics:metrics
                      views:viewsDictionary];

// Set alignment of pauseButton and replayButton
constraints = [constraints arrayByAddingObjectsFromArray:[NSLayoutConstraint
  constraintsWithVisualFormat:@"|-buttonPadding-[_pauseButton]"
                      options:NSLayoutFormatAlignAllCenterY
                      metrics:metrics
                      views:viewsDictionary]];
constraints = [constraints arrayByAddingObjectsFromArray:[NSLayoutConstraint
  constraintsWithVisualFormat:@"|-buttonPadding-[_replayButton]"
                      options:NSLayoutFormatAlignAllCenterY
                      metrics:metrics
                        views:viewsDictionary]];

// Not sure why using NSLayoutFormatAlignAllCenterY above doesn't center the buttons vertically,
// so we need another set of constraints to center them vertically.
constraints = [constraints arrayByAddingObject:
  [NSLayoutConstraint constraintWithItem:_pauseButton
                               attribute:NSLayoutAttributeCenterY
                               relatedBy:NSLayoutRelationEqual
                                  toItem:_pauseButton.superview
                               attribute:NSLayoutAttributeCenterY
                              multiplier:1.0f
                                constant:0]];
constraints = [constraints arrayByAddingObject:
  [NSLayoutConstraint constraintWithItem:_replayButton
                               attribute:NSLayoutAttributeCenterY
                               relatedBy:NSLayoutRelationEqual
                                  toItem:_replayButton.superview
                               attribute:NSLayoutAttributeCenterY
                              multiplier:1.0f
                                constant:0]];

2 个答案:

答案 0 :(得分:1)

您可以尝试使用

NSArray *constraints = [NSLayoutConstraint
constraintsWithVisualFormat:@"|[_playButton(==_pauseButton)]"
                  options:0
                  metrics:nil
                  views:viewsDictionary];

constraints = [NSLayoutConstraint
constraintsWithVisualFormat:@"V:|[_playButton(==_pauseButton)]"
                  options:0
                  metrics:nil
                  views:viewsDictionary];

[self addConstraint:[NSLayoutConstraint constraintWithItem:_playButton 
    attribute:NSLayoutAttributeCenterY 
    relatedBy:NSLayoutRelationEqual 
    toItem:_pauseButton 
    attribute:NSLayoutAttributeCenterY 
    multiplier:1.0f 
    constant:0.0f]];

[self addConstraint:[NSLayoutConstraint constraintWithItem:_playButton 
    attribute:NSLayoutAttributeCenterX 
    relatedBy:NSLayoutRelationEqual 
    toItem:_pauseButton 
    attribute:NSLayoutAttributeCenterX 
    multiplier:1.0f 
    constant:0.0f]];

答案 1 :(得分:1)

这个答案解决了Edit2下的代码。

你在构建一个漂亮的水平行的各种按钮方面做得很好,即_playButton - > _minimizeButton。但是,格式选项NSLayoutFormatAlignAllCenterY仅相对于所有其他按钮垂直对齐每个按钮。您仍然没有建立一个规则来沿垂直轴相对于行的容器视图定位按钮行。

由于所有按钮已经相对于彼此垂直对齐,您所要做的就是向其中一个按钮(任何按钮)添加垂直轴类型约束。这是一个假设的例子,它将播放按钮顶部的40个点从容器视图的顶部开始。如果你想要一个更实际的例子,我需要更好地理解整体布局。

[[containerView addConstraint:[NSLayoutConstraint constraintWithItem:_playButton attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:containerView attribute:NSLayoutAttributeTop multiplier:1.0f constant:40.0f]];