Чтобы сделать это с помощью автоматического макета, вы должны создать дополнительные представления, чтобы заполнить пробелы между текстовыми полями.
Напомним, что ограничение автоматической компоновки в основном является линейным уравнением A = m * B + c
. A
- это атрибут одного вида (например, координата Y от нижнего края viewA
) и B
- это атрибут другого вида (например, координата Y верхнего края viewB
). m
и c
являются константами. Так, например, чтобы выложить viewA
и viewB
, так что есть 30 точек между дном viewA
и вершиной viewB
, мы могли бы создать ограничение, где m
равно 1 и c
-30.
Проблема, с которой вы сталкиваетесь, заключается в том, что вы хотите использовать одно и то же значение для c
через 13 различных ограничений, и вы хотите, чтобы автоматический макет вычислил, что значение c
для вас. Автоматический макет просто не может этого сделать. Не напрямую. Автомакет может вычислять только атрибуты представлений; он не может вычислить константы m
и c
.
Существует способ сделать автоматическую компоновку, поместите взгляды туда, где вы хотите: обновить пробелы между текстовыми полями как дополнительные (невидимые) виды. Вот пример только с 3 текстовых полей:
Мы создадим ограничение приколоть верхний край каждой распорки к нижнему краю текстового поля над ним. Мы также создадим ограничение, чтобы прикрепить нижний край каждого разделителя к верхнему краю текстового поля под ним. И, наконец, мы создадим ограничение, чтобы заставить каждую прокладку иметь ту же высоту, что и самая верхняя проставка.
Нам понадобится две переменные экземпляра, чтобы установить вещи: массив текстовых полей (в порядке сверху вниз), а также ссылку на верхний взгляд распорной:
@implementation ViewController {
NSMutableArray *textFields;
UIView *topSpacer;
}
Мы» ll создайте текстовые поля и разделители в коде, так как трудно показать xib в ответе stackoverflow.Мы пнуть вещи в viewDidLoad
:
- (void)viewDidLoad {
[super viewDidLoad];
self.view.translatesAutoresizingMaskIntoConstraints = NO;
[self addTextFields];
[self addSpacers];
}
Так как мы будем использовать автоматическую раскладку, нам нужно отключить translatesAutoresizingMaskIntoConstraints
для защиты системы от создания дополнительных ограничений.
Мы создаем каждый текстовое поле, дайте ему фиктивный текст и установить ограничения для ее горизонтального положения и размера:
- (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)]];
}
Если вы сделаете это правильно, вы получите результат, как это:
Вы можете найти полный пример проекта в this github repository.
В вашей 'строки constraintsWithVisualFormat', ваше первое«пространство»является константой 50, и вы используете только 12«космические»идентификаторы , хотя вы рассчитали 13. Либо измените значение '50' на' (пробел) ', либо вычислите' spaceBetweenEachButton' как 'unusedHorizontalSpace/12-50. Не уверен, что это сработает, но это стоит того. –
Что вы на самом деле получаете с кодом выше? –
@ Хэри Карам Синг См. Второе изображение в вопросе. – CRDave