iOS Autolayout垂直相等的空間來填充父檢視
我有一個檢視控制器與12個UITextFields.
它適合3.5“顯示非常好.
我需要將其設定為iPhone 5(4英寸顯示器),以便所有UITextField通過在其間新增額外的空間覆蓋整個UIView.
我試圖通過自動佈局來做,但是它不能正常工作.
這是我的程式碼:
- (void) viewWillLayoutSubviews { int h = txt1.bounds.size.height * 12; float unusedHorizontalSpace = self.view.bounds.size.height - h ; NSNumber* spaceBetweenEachButton=[NSNumber numberWithFloat: unusedHorizontalSpace / 13 ] ; NSMutableArray *constraintsForButtons = [[NSMutableArray alloc] init]; [constraintsForButtons addObjectsFromArray: [NSLayoutConstraint constraintsWithVisualFormat: @"V:|-50-[txt1(==30)]-(space)-[txt2(==txt1)]-(space)-[txt3(==txt1)]-(space)-[txt4(==txt1)]-(space)-[txt5(==txt1)]-(space)-[txt6(==txt1)]-(space)-[txt7(==txt1)]-(space)-[txt8(==txt1)]-(space)-[txt9(==txt1)]-(space)-[txt10(==txt1)]-(space)-[txt11(==txt1)]-(space)-[txt12]-(space)-|" options: NSLayoutFormatAlignAllCenterX metrics: @{@"space":spaceBetweenEachButton} views: NSDictionaryOfVariableBindings(txt1,txt10,txt11,txt12,txt2,txt3,txt4,txt5,txt6, txt7,txt8,txt9)]]; [self.view addConstraints:constraintsForButtons]; }
如果我做[txt12(== txt1)],那麼它顯示與3.5“螢幕相同,並留下下面的空格.
我在哪裡犯錯?
要使用自動佈局執行此操作,您必須建立額外的檢視來填充文字欄位之間的空格.
回想自動佈局約束基本上是線性方程式A = m * B c. A是一個檢視的屬性(例如,viewA的底邊的Y座標),B是另一個檢視的屬性(例如,viewB的頂部邊緣的Y座標). m和c是常數.所以,例如,要設定viewA和viewB,以便在viewA的底部和viewB的頂部之間有30個點,我們可以建立一個約束,其中m是1,c是-30.
您遇到的問題是您想要跨13個不同約束使用相同的值,並且您希望自動佈局為您計算該c值.汽車佈局根本無法做到這一點.不直接自動佈局只能計算檢視的屬性;它不能計算m和c常數.
有一種方法使自動佈局將檢視放在您想要的位置:將文字欄位之間的空格重新列為附加(不可見)檢視.這裡有一個只有3個文字欄位的例子:
我們將建立一個約束,將每個間隔件的頂部邊緣固定在其上方的文字框的底部邊緣.我們還將建立一個約束,將每個間隔件的底部邊緣固定到其下方的文字欄位的頂部邊緣.最後,我們將建立一個約束,以強制每個間隔物具有與頂部間隔物相同的高度.
我們需要一個兩個例項變數來設定:文字欄位的陣列(從上到下的順序),以及對最頂層間隔檢視的引用:
@implementation ViewController { NSMutableArray *textFields; UIView *topSpacer; }
我們將在程式碼中建立文字欄位和間隔符,因為在stackoverflow答案中很難顯示xib.我們在viewDidLoad中踢東西:
- (void)viewDidLoad { [super viewDidLoad]; self.view.translatesAutoresizingMaskIntoConstraints = NO; [self addTextFields]; [self addSpacers]; }
由於我們要使用自動佈局,所以我們需要關閉translateAutoresizingMaskIntoConstraints來避免系統建立額外的約束.
我們建立每個文字欄位,給它一些虛擬文字,併為其水平位置和大小設定約束:
- (void)addTextFields { textFields = [NSMutableArray array]; for (int i = 0; i < 12; ++i) { [self addTextField]; } } - (void)addTextField { UITextField *field = [[UITextField alloc] init]; field.backgroundColor = [UIColor colorWithHue:0.8 saturation:0.1 brightness:0.9 alpha:1]; field.translatesAutoresizingMaskIntoConstraints = NO; field.text = [field description]; [self.view addSubview:field]; [field setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical]; [field setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-[field]-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(field)]]; [textFields addObject:field]; }
我們將使用一個環來建立間隔物,但是我們建立了與中間間隔物不同的頂部和底部墊片,因為我們需要將頂部和底部墊片固定在超級檢視中:
- (void)addSpacers { [self addTopSpacer]; for (int i = 1, count = textFields.count; i < count; ++i) { [self addSpacerFromBottomOfView:textFields[i - 1] toTopOfView:textFields[i]]; } [self addBottomSpacer]; }
以下是我們如何建立頂部間隔符並設定其約束.其頂部邊緣固定在超級檢視中,其底部邊緣被固定到第一個(最上面的)文字欄位.我們將頂部間隔物儲存在例項變數topSpacer中,因此我們可以約束其他間隔物與頂部間隔物具有相同的高度.
- (void)addTopSpacer { UIView *spacer = [self newSpacer]; UITextField *field = textFields[0]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[spacer][field]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(spacer, field)]]; topSpacer = spacer; }
以下是我們如何實際建立一個間隔檢視.這只是一個隱藏的看法.由於我們不關心它的水平尺寸或位置,我們只將其固定在超級檢視的左右邊緣.
- (UIView *)newSpacer { UIView *spacer = [[UIView alloc] init]; spacer.hidden = YES; // Views participate in layout even when hidden. spacer.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:spacer]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|[spacer]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(spacer)]]; return spacer; }
要在兩個文字檢視之間建立一個“中間”間距,我們將其固定在文字的底部邊緣
欄位上方和文字欄位的上邊緣.我們還將其高度限制為等於頂部間隔物的高度.
- (void)addSpacerFromBottomOfView:(UIView *)overView toTopOfView:(UIView *)underView { UIView *spacer = [self newSpacer]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[overView][spacer(==topSpacer)][underView]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(spacer, overView, underView, topSpacer)]]; }
要建立底部間隔符,我們將其固定到最後一個文字欄位和超級檢視.我們還將其高度限制為等於頂部間隔物的高度.
- (void)addBottomSpacer { UIView *spacer = [self newSpacer]; UITextField *field = textFields.lastObject; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[field][spacer(==topSpacer)]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(spacer, field, topSpacer)]]; }
如果你這樣做,你會得到如下結果:
您可以在 ofollow,noindex" target="_blank">this github repository 找到一個完整的示例專案.
http://stackoverflow.com/questions/17089427/ios-autolayout-vertically-equal-space-to-fill-parent-view