2013-07-31 110 views
2

我有一個簡單的佈局,其中有一個containerView開始在整個屏幕上。裏面,我有兩個垂直子視圖 - topView (green), botView (orange)需要相同的高度,應該有50%的高度。NSLayoutConstraint子視圖不會自動調整大小以適應容器視圖

發射後,我從屏幕上向下滑動一個視圖(藍色),導致containerView調整到較短的高度。

我會希望發生的是,topViewbotView既能變短,在containerView內保持其甚至高度,但實際發生的事情是,內部意見沒有調整,儘管有一個約束這樣做。

enter image description here

因爲這段代碼有一些基於代碼的限制,有的IB的,here是一個示例項目,看看它在行動。這是一個被忽略的約束:

NSLayoutConstraint *c1 = [NSLayoutConstraint constraintWithItem:self.topView 
                 attribute:NSLayoutAttributeHeight 
                 relatedBy:NSLayoutRelationEqual 
                 toItem:self.containerView 
                 attribute:NSLayoutAttributeHeight 
                multiplier:0.5f 
                 constant:0.f]; 
[self.containerView addConstraint:c1]; 

,並調整大小視圖代碼:

- (void)resizeViews { 

    __weak UAViewController *weakSelf = self; 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     [UIView animateWithDuration:0.25 animations:^{ 
      weakSelf.slideInView.frame = CGRectMake(CGRectGetMinX(weakSelf.view.bounds), 
                CGRectGetMaxY(weakSelf.view.bounds) - CGRectGetHeight(weakSelf.slideInView.frame), 
                CGRectGetWidth(weakSelf.view.bounds), 
                CGRectGetHeight(weakSelf.slideInView.frame)); 

      weakSelf.containerView.frame = CGRectMake(CGRectGetMinX(weakSelf.view.bounds), 
                 CGRectGetMinY(weakSelf.view.bounds), 
                 CGRectGetWidth(weakSelf.view.bounds), 
                 CGRectGetMaxY(weakSelf.view.bounds) - CGRectGetHeight(weakSelf.slideInView.frame)); 

     }]; 
    }); 

} 

什麼我錯在這裏做什麼?

+0

順便說一句,你爲什麼要在'resizeViews'中做'dispatch_async'?這不是必須的(除非你從其他隊列中調用它,如果你這樣做,我會感到驚訝)。但它沒有實際意義,因爲如果你正在做自動佈局,你不應該用'frame'屬性來解決問題。修改您的約束,並讓約束引擎進行適當的「框架」更改。 – Rob

+0

dispatch_async正在從調試應用程序的計時器線程中調用。 – coneybeare

回答

4

我很驚訝你將frame設置爲一個視圖。通常在自動佈局中,您可以通過更改約束constant而不是更改frame來在視圖中滑動。例如,假設你對容器的子視圖的約束是這樣定義的(爲了簡單起見,因爲兩個視圖應該佔用容器的50%,最容易通過將兩個子視圖定義爲同一高度):

[containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[topView][botView(==topView)]|" options:0 metrics:nil views:views]]; 
[containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[topView]|" options:0 metrics:nil views:views]]; 
[containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[botView]|" options:0 metrics:nil views:views]]; 

而且,讓事情變得簡單,定義視圖與關係,像這樣的幻燈片的上海華容器之間的關係,:

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[containerView][slideInView]|" options:0 metrics:nil views:views]]; 
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[containerView]|" options:0 metrics:nil views:views]]; 
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[slideInView]|" options:0 metrics:nil views:views]]; 

// set the slide in view's initial height to zero 

NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:slideInView 
                    attribute:NSLayoutAttributeHeight 
                    relatedBy:NSLayoutRelationEqual 
                     toItem:nil 
                    attribute:NSLayoutAttributeNotAnAttribute 
                    multiplier:1.0 
                    constant:0.0]; 
[self.view addConstraint:heightConstraint]; 

然後,當你想在「幻燈片放映」中滑動,只是動畫其高度的相應變化:

heightConstraint.constant = 100; 
[UIView animateWithDuration:1.0 animations:^{ 
    [self.view layoutIfNeeded]; 
}]; 

這樣:

two views

現在,你可以是容器的高度的X%,也高度做到這一點,但你可以用VFL很容易做到,但它應該可以正常工作。你也可以在幻燈片中滑動它的頂部約束(但是這很麻煩,因爲這樣你就不得不重新計算旋轉的頂部約束,這是我在這個簡單的模型中不想做的)。

但你明白了。只需將容器視圖的高度或底部約束定義爲與視圖中的幻燈片相關,然後通過調整其約束來在視圖中爲幻燈片設置動畫效果,並且如果您已正確定義所有約束,則它將優雅地動畫化全部在視圖的約束條件中更改幻燈片之後爲動畫layoutIfNeeded設置了四個視圖(容器,視圖中的幻燈片和容器的兩個子視圖)。

+0

你在說什麼是有道理的,我已經將這些改變應用到了我的項目中,但是我一直無法複製你的截圖 - 「無法同時滿足約束條件」。你能否傳回你在這裏使用的修改過的proj,以便我可以知道我要去哪裏? – coneybeare

+0

@coneybeare通常無法滿足約束是忽略爲您的編程創建的視圖設置'translatesAutoresizingMaskIntoConstraints'爲'NO'的結果。我必須承認,我沒有看過你的項目(它有時可能會經過其他人的項目而感到毛骨悚然),從頭開始做起來更容易。我剛創建了一個空白的應用程序,並在視圖控制器的'viewDidLoad'中投入了下面的代碼:http://pastie.org/8194565#希望能夠說明這個概念。 – Rob

+0

我能夠通過使用pastie代碼來複制您的結果,但我很難理解使用IB生成的視圖時爲什麼同樣的事情不起作用。我在所有5個視圖中將translatesAutoresizingMaskIntoConstraints設置爲NO,在故事板中沒有任何限制,但仍然出現錯誤。你可以看看這個(非常簡單)的示例程序嗎? http://cloud.coneybeare.net/QZ6G – coneybeare

相關問題