簡體   English   中英

自動布局(約束)中心2在父視圖中並排顯示

[英]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邊等於其viewCenteredInLeftSectionviewCenteredInLeftSection )。
  • 使label的尾隨邊緣等於其viewCenteredInLeftSection視圖( viewCenteredInLeftSection )。
  • 使clockImage的后緣距離label的前緣標准距離。

viewCenteredInLeftSection

我無法在Interface Builder中調整iOS UIViews的大小,所以我為OS X制作了我的示例,我完全可以在Interface Builder中完成。 如果您在Interface Builder中遇到上述限制時遇到問題,請告訴我,我將發布將創建它們的代碼。

2014-08-26編輯

Luda ,這里是Xcode 5的Pin和Align菜單,也可以在Xcode的菜單欄中找到:

對齊菜單Pin菜單

下面是我的示例在Interface Builder中的樣子。 藍色視圖是原始問題的“父視圖”,即給定視圖,圖像和標簽應居中。

我添加了綠色視圖(我將其命名為viewCenteredInLeftSection )作為“父視圖”的子視圖。 然后我突出顯示它並使用“對齊”菜單“容器中的水平中心”和“容器中的垂直中心”來創建約束以定義其位置。

我添加了時鍾圖像作為viewCenteredInLeftSection的子視圖,其中約束定義了它的寬度和高度。 我突出顯示了時鍾圖像和viewCenteredInLeftSection ,然后使用“對齊”>“前沿”,“對齊”>“頂邊”和“對齊”>“底邊”應用約束。

我將標簽添加為viewCenteredInLeftSection的子視圖,將其定位為時鍾圖像的標准Aqua空間距離 我突出顯示了標簽和viewCenteredInLeftSection ,然后使用“對齊”>“尾隨邊緣”應用了約束。

使用Xcode 5的Interface Builder與Xcode 4相比,這容易創建。

Interface Builder

我想出了一種不添加其他視圖的方法:

 [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項目,假設你的所有項目都有約束大小,不會增長

  1. 在物品的每一側放置2個墊片。 將墊片錨定到父邊緣。 將您的第一個和最后一個項目錨定到錨點。 最后,指定1個間隔物以具有另一個間隔物的寬度。 您無需明確設置任何間隔尺寸,因為它將被解決

    • spacer1 - > left = parent:left width = spacer2:width
    • spacer2 - > right = parent:right
    • yourFirstItem - > left = spacer1:right
    • yourLastItem - > right = spacer2:left
  2. 如果間隔物不是你的東西,而你和你的物品數量奇數,則將中間物品置於父物的中心。 此外,請確保第一個和最后一個項目未錨定到父邊緣。

    • yourMiddleItem = centerX = parent:centerX
    • otherItems-> yourMiddleItem <-otherItems
  3. 如果間隔物不是您的東西,並且您具有偶數個項目,則將2個內部項目的邊緣居中放置到父項目的中心。 此外,請確保第一個和最后一個項目未錨定到父邊緣。

    • leftMiddleItem - > right = parent:centerX
    • rightMiddleItem - > left = parent:centerX
    • otherItems-> leftMiddleItem rightMiddleItem <-otherItems
  4. 你也可以將一個看不見的占位符集中在中心,然后錨定到那個,但是在約束時你仍然需要考慮奇數/偶數項,所以我不推薦這種方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM