2013-12-20 41 views
0

我想将几个按钮堆叠在一起,然后显示/隐藏它们作为切换方式。 (想象一下视频播放器中的播放/暂停/重放按钮)。iOS:使用NSLayoutConstraint将对象堆叠在彼此的顶部

是否可以使用NSLayoutConstraint来做到这一点?

另外,也许有更好的方法来在iOS中创建多状态按钮?

这里是我试过,但obvoiusly因为这使他们旁边的海誓山盟不起作用:

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]]; 
+0

我知道你已经接受了一个答案,但你确定你的布局不含糊吗?在viewDidAppear中设置一个断点,然后在调试器中剪切并粘贴以下内容:po [[UIWindow keyWindow] _autolayoutTrace]。 – bilobatum

+0

是的,任何想法如何解决它? – Geoff

+0

你需要在'contraintsWithVisualFormat'前加入'H:'和'V:'吗? – ansible

回答

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]]; 
+0

你是否在这些中使用'_playButton'而不是'_infoButton'? – Geoff

+0

修复了错误并改进了代码。 – dasdom

+0

此代码给了我一些尝试的想法,所以我更新了我的代码(请参阅更新的q)。我现在只需要计算播放/重放按钮的真实间距。任何想法为什么'NSLayoutFormatAlignAllCenterY'不适合那些?出于某种原因,它们比其他元素高。 – Geoff

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