[英]Two views, one below another in portrait and side by side in landscape using layout constraints
[英]Auto Layout (Constraints) Center 2 side by side views in a parent view
我試圖弄清楚如何使用自動布局(iOS6)和約束來做到這一點。
基本上我將我的大視圖分為底部的兩個部分。 在這些部分(目前是子視圖)內部,我有一個圖像視圖和一個標簽。 我希望以兩邊為中心,使用可變長度的文本。
我的頭腦主要是圍繞汽車布局,但我不確定最好的方法。 我傾向於認為這在IB中是不可能的,但是在代碼中。
繼續嘗試解決這個問題,但與此同時,我正在努力創建這個例子。
這就是你要追求的嗎?
我是通過在你的leftSection
添加一個視圖(名為viewCenteredInLeftSection
),然后將時鍾圖像和標簽添加為具有這些約束的子視圖來實現的:
viewCenteredInLeftSection
的CenterX和CenterY等於其leftSection
的( leftSection
)。 clockImage
的Top,Bottom和Leading邊等於其viewCenteredInLeftSection
( viewCenteredInLeftSection
)。 label
的尾隨邊緣等於其viewCenteredInLeftSection
視圖( viewCenteredInLeftSection
)。 clockImage
的后緣距離label
的前緣標准距離。 我無法在Interface Builder中調整iOS UIViews的大小,所以我為OS X制作了我的示例,我完全可以在Interface Builder中完成。 如果您在Interface Builder中遇到上述限制時遇到問題,請告訴我,我將發布將創建它們的代碼。
2014-08-26編輯
Luda ,這里是Xcode 5的Pin和Align菜單,也可以在Xcode的菜單欄中找到:
下面是我的示例在Interface Builder中的樣子。 藍色視圖是原始問題的“父視圖”,即給定視圖,圖像和標簽應居中。
我添加了綠色視圖(我將其命名為viewCenteredInLeftSection
)作為“父視圖”的子視圖。 然后我突出顯示它並使用“對齊”菜單“容器中的水平中心”和“容器中的垂直中心”來創建約束以定義其位置。
我添加了時鍾圖像作為viewCenteredInLeftSection
的子視圖,其中約束定義了它的寬度和高度。 我突出顯示了時鍾圖像和viewCenteredInLeftSection
,然后使用“對齊”>“前沿”,“對齊”>“頂邊”和“對齊”>“底邊”應用約束。
我將標簽添加為viewCenteredInLeftSection
的子視圖,將其定位為距時鍾圖像的標准Aqua空間距離 。 我突出顯示了標簽和viewCenteredInLeftSection
,然后使用“對齊”>“尾隨邊緣”應用了約束。
使用Xcode 5的Interface Builder與Xcode 4相比,這更容易創建。
我想出了一種不添加其他視圖的方法:
[aView addConstraint:[NSLayoutConstraint constraintWithItem:viewOnLeft attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationLessThanOrEqual toItem:aView attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]];
[aView addConstraint:[NSLayoutConstraint constraintWithItem:viewOnRight attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationLessThanOrEqual toItem:aView attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]];
您還可以更改常量以在視圖之間創建間隙。
-X
+X
我花了一點時間,但我找到了一個非常可靠的解決方案。 我想出了John Sauer提供的相同解決方案,但不想添加另一個視圖來包裝這些。
答案需要三個步驟。
1)我的子視圖的寬度包含其他兩個,我稱之為leftInfoSection
,需要由它的內容決定。 這使得它不需要對超視圖(或其他視圖)具有左右約束來確定它的寬度。 這是一個真正的關鍵,很多東西都是讓孩子們定義寬度。
2)我仍然必須在IB中有一個主要約束,因為它有一個有效的布局。 (它需要知道水平放置leftInfoSection
位置)。 將一個約束連接到您的代碼中,以便您可以刪除它。 除此之外,我有一個尾隨約束GTE垂直分頻器+3。
3)最后的關鍵是考慮你必須使用哪些信息(在代碼中,因為IB是有限的)。 我意識到我知道我的部分上方的水平分隔線的中心,並且我的leftInfoSection
的中心將是該水平條的中心減去水平條寬度的1/4。 這是左側和右側的最終代碼:
// remove the unwanted constraint to the right side of the thumbnail
[self.questionBox removeConstraint:self.leftInfoViewLeadingConstraint];
// calculate the center of the leftInfoView
CGFloat left = self.horizontalDividerImageView.frame.size.width/4 * -1;
// constrain the center of the leftInfoView to the horizontal bar center minus a quarter of it to center things
[self.questionBox addConstraint:[NSLayoutConstraint constraintWithItem:self.leftInfoView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.horizontalDividerImageView attribute:NSLayoutAttributeCenterX multiplier:1 constant:left]];
// remove the unwanted constraint to the right side of the questionBox
[self.questionBox removeConstraint:self.rightInfoViewTrailingConstraint];
// calculate the center of the rightInfoView
CGFloat right = left * -1;
// constrain the center of the rightInfoView to the horizontal bar center plus a quarter of it to center things
[self.questionBox addConstraint:[NSLayoutConstraint constraintWithItem:self.rightInfoView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.horizontalDividerImageView attribute:NSLayoutAttributeCenterX multiplier:1 constant:right]];
結果:
此外,IB可能會非常討厭它如何自動更新約束。 當我試圖將子視圖上的前導和尾隨約束定義為0時,它將保持斷開一個或另一個並對超視圖進行約束以定義寬度。 訣竅是暫時保留不需要的約束,但將其優先級降低到999.然后我能夠創建但子視圖約束來定義寬度。
在斯坦福大學的ios 7講座中考慮了這方面的解決方案。它工作得很漂亮。這里有解決方案。 (這里sdfssfg ......東西是label1和efsdfg ....東西是label2)
這很好用,但需要2個間隔UIView:
UIView *spacer1 = [[UIView alloc] init];
spacer1.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:spacer1];
UIView *spacer2 = [[UIView alloc] init];
spacer2.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:spacer2];
NSDictionary *views = NSDictionaryOfVariableBindings(spacer1, spacer2, imageView, label);
[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[spacer1(>=0)][imageView]-4-[label][spacer2(==spacer1)]|" options:0 metrics:nil views:views];
for (int i = 0; i < constraintsArray.count; i++) {
[self.view addConstraint:constraintsArray[i]];
}
在iOS 9之后,實現此目的的另一個選擇是使用堆棧視圖
有幾種方法可以做到這一點。 從基本的角度來說,這里是如何居中1..n項目,假設你的所有項目都有約束大小,不會增長 。
在物品的每一側放置2個墊片。 將墊片錨定到父邊緣。 將您的第一個和最后一個項目錨定到錨點。 最后,指定1個間隔物以具有另一個間隔物的寬度。 您無需明確設置任何間隔尺寸,因為它將被解決 。
如果間隔物不是你的東西,而你和你的物品數量奇數,則將中間物品置於父物的中心。 此外,請確保第一個和最后一個項目未錨定到父邊緣。
如果間隔物不是您的東西,並且您具有偶數個項目,則將2個內部項目的邊緣居中放置到父項目的中心。 此外,請確保第一個和最后一個項目未錨定到父邊緣。
你也可以將一個看不見的占位符集中在中心,然后錨定到那個,但是在約束時你仍然需要考慮奇數/偶數項,所以我不推薦這種方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.