2013-12-20 64 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]];