Шрифт:
Интервал:
Закладка:
Здесь мы видим, что оба текстовых поля сопровождаются применяемыми к ним по горизонтали и вертикали ограничениями, описанными на языке визуального форматирования. Кнопка регистрации, в свою очередь, имеет только ограничение по вертикали, также описанное на языке визуального форматирования. Почему? Оказывается, что на языке визуального форматирования невозможно выразить центрирование компонента пользовательского интерфейса по горизонтали. Для решения этой задачи воспользуемся приемом, изученным в разделе 3.1. Но пусть это вас не смущает — все равно стоит пользоваться языком визуального форматирования и наслаждаться его потенциалом. Да, он несовершенен, но это не повод от него отказываться.
Теперь определим компоненты пользовательского интерфейса как закрытые (приватные) свойства в файле реализации контроллера вида:
@interface ViewController ()
@property (nonatomic, strong) UITextField *textFieldEmail;
@property (nonatomic, strong) UITextField *textFieldConfirmEmail;
@property (nonatomic, strong) UIButton *registerButton;
@end
@implementation ViewController
<# Оставшаяся часть вашего кода находится здесь #>
Что дальше? Теперь нужно сконструировать сами компоненты пользовательского интерфейса в файле реализации контроллера вида. Итак, напишем два удобных метода, которые нам в этом помогут. Опять же не забывайте: мы не собираемся здесь задавать фреймы этих компонентов. Позже нам в этом поможет автоматическая компоновка:
— (UITextField *) textFieldWithPlaceholder:(NSString *)paramPlaceholder{
UITextField *result = [[UITextField alloc] init];
result.translatesAutoresizingMaskIntoConstraints = NO;
result.borderStyle = UITextBorderStyleRoundedRect;
result.placeholder = paramPlaceholder;
return result;
}
— (void) constructUIComponents{
self.textFieldEmail =
[self textFieldWithPlaceholder:@"Email"];
self.textFieldConfirmEmail =
[self textFieldWithPlaceholder:@"Confirm Email"];
self.registerButton = [UIButton buttonWithType: UIButtonTypeSystem];
self.registerButton.translatesAutoresizingMaskIntoConstraints = NO;
[self.registerButton setTitle:@"Register" forState: UIControlStateNormal];
}
Метод textFieldWithPlaceholder: просто создает текстовые поля, содержащие заданный подстановочный текст, а метод constructUIComponents, в свою очередь, создает два текстовых поля, пользуясь вышеупомянутым методом и кнопкой. Вы, вероятно, заметили, что мы присвоили свойству translatesAutoresizingMaskIntoConstraints всех наших компонентов пользовательского интерфейса значение NO. Так мы помогаем UIKit не перепутать маски автоматической подгонки размеров с ограничениями автоматической компоновки. Как вы знаете, можно задавать маски автоматической подгонки размеров для компонентов пользовательского интерфейса и контроллеров видов как в коде, так и в конструкторе интерфейсов. Об этом мы говорили в главе 1. Устанавливая здесь значение NO, мы гарантируем, что UIKit ничего не перепутает и не будет автоматически преобразовывать маски автоматической подгонки размера в ограничения автоматической компоновки. Эту функцию необходимо задавать, если вы смешиваете свойства автоматической компоновки компонентов с ограничениями макета. Как правило, следует устанавливать это значение у всех компонентов пользовательского интерфейса в NO всякий раз, когда вы работаете с ограничениями автоматической компоновки. Исключение составляют случаи, в которых вы специально приказываете UIKit преобразовать маски автоматической подгонки размеров в ограничения автоматической компоновки.
Мы создаем компоненты пользовательского интерфейса, но вполне очевидно, что методу viewDidLoad контроллера вида необходимо добавить к виду все три компонента пользовательского интерфейса. Почему бы не написать еще один небольшой метод, который будет заниматься именно этим?
— (void) addUIComponentsToView:(UIView *)paramView{
[paramView addSubview: self.textFieldEmail];
[paramView addSubview: self.textFieldConfirmEmail];
[paramView addSubview: self.registerButton];
}
Итак, почти все готово. Следующая крупная задача — создать методы, которые позволят сконструировать и собрать все ограничения в массив. У нас также есть удобный четвертый метод, который собирает все ограничения от всех трех компонентов пользовательского интерфейса и объединяет их в общий большой массив. Вот как мы его реализуем:
— (NSArray *) emailTextFieldConstraints{
NSMutableArray *result = [[NSMutableArray alloc] init];
NSDictionary *viewsDictionary =
NSDictionaryOfVariableBindings(_textFieldEmail);
[result addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat: kEmailTextFieldHorizontal
options:0
metrics: nil
views: viewsDictionary]
];
[result addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat: kEmailTextFieldVertical
options:0
metrics: nil
views: viewsDictionary]
];
return [NSArray arrayWithArray: result];
}
— (NSArray *) confirmEmailTextFieldConstraints{
NSMutableArray *result = [[NSMutableArray alloc] init];
NSDictionary *viewsDictionary =
NSDictionaryOfVariableBindings(_textFieldConfirmEmail, _textFieldEmail);
[result addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat: kConfirmEmailHorizontal
options:0
metrics: nil
views: viewsDictionary]
];
[result addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat: kConfirmEmailVertical
options:0
metrics: nil
views: viewsDictionary]
];
return [NSArray arrayWithArray: result];
}
— (NSArray *) registerButtonConstraints{
NSMutableArray *result = [[NSMutableArray alloc] init];
NSDictionary *viewsDictionary =
NSDictionaryOfVariableBindings(_registerButton, _textFieldConfirmEmail);
[result addObject:
[NSLayoutConstraint constraintWithItem: self.registerButton
attribute: NSLayoutAttributeCenterX
relatedBy: NSLayoutRelationEqual
toItem: self.view
attribute: NSLayoutAttributeCenterX
multiplier:1.0f
constant:0.0f]
];
[result addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat: kRegisterVertical
options:0
metrics: nil
views: viewsDictionary]
];
return [NSArray arrayWithArray: result];
}
— (NSArray *)constraints{
NSMutableArray *result = [[NSMutableArray alloc] init];
[result addObjectsFromArray: [self emailTextFieldConstraints]];
[result addObjectsFromArray: [self confirmEmailTextFieldConstraints]];
[result addObjectsFromArray: [self registerButtonConstraints]];
return [NSArray arrayWithArray: result];
}
Фактически здесь мы имеем метод экземпляра constraints, относящийся к контроллеру вида; этот метод собирает ограничения от всех трех компонентов пользовательского интерфейса, а потом возвращает их все как один большой массив. Теперь переходим к основной части контроллера — методу viewDidLoad:
— (void)viewDidLoad{
[super viewDidLoad];
[self constructUIComponents];
[self addUIComponentsToView: self.view];
[self.view addConstraints: [self constraints]];
}
Этот метод просто собирает пользовательский интерфейс, добавляя сам к себе все компоненты пользовательского интерфейса и связанные с ними ограничения. При этом он использует методы, написанные нами ранее. Отлично, но что мы увидим на экране, когда запустим эту программу? Мы уже видели, как этот интерфейс выглядит на устройстве, работающем в книжной ориентации (см. рис. 3.4). А теперь повернем устройство и посмотрим, что получится при альбомной ориентации (рис. 3.5).
Рис. 3.5. Ограничения функционируют в альбомном режиме не хуже, чем в книжном
См. также
Разделы 3.0 и 3.1.
3.3. Применение ограничений при работе с перекрестными видами
Постановка задачи
Требуется выровнять компонент пользовательского интерфейса относительно другого компонента пользовательского интерфейса, притом что родительские элементы у этих компонентов разные.
Решение
Ориентируясь на рис. 3.1, убедитесь, что вам удалось найти ближайший общий вышестоящий вид, являющийся родителем для интересующих вас компонентов пользовательского интерфейса. Затем добавьте ограничения к этому вышестоящему виду.
Обсуждение
Прежде чем углубляться в детали, разберемся, в чем же заключаются ограничения перекрестных видов. Мне кажется, что суть проблемы удобнее изобразить на картинке, а не описывать словами, — предлагаю вашему вниманию рис. 3.6.
- QT 4: программирование GUI на С++ - Жасмин Бланшет - Программирование
- Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен - Программирование
- C# для профессионалов. Том II - Симон Робинсон - Программирование
- Стандарты программирования на С++. 101 правило и рекомендация - Герб Саттер - Программирование
- Программирование игр и головоломок - Жак Арсак - Программирование
- Генерация высококачественного кода для программ, написанных на СИ - Филипп Хислей - Программирование
- Программирование на Python с нуля - Максим Кононенко - Программирование
- C# 4.0: полное руководство - Герберт Шилдт - Программирование
- Microsoft Visual C++ и MFC. Программирование для Windows 95 и Windows NT. Часть 2 - Александр Фролов - Программирование
- От «Энигмы» до ChatGPT - Рустам Агамалиев - Программирование / Экономика