Обсуждение
Обсуждение
Прежде чем углубляться в детали, разберемся, в чем же заключаются ограничения перекрестных видов. Мне кажется, что суть проблемы удобнее изобразить на картинке, а не описывать словами, — предлагаю вашему вниманию рис. 3.6.
Рис. 3.6. Важные ограничения, налагаемые перекрестными видами на две кнопки
На этом рисунке к видам применяется немало ограничений. Разберем их по порядку, разложив все по полочкам.
• Есть основной вид с контроллером, в этом виде расположены еще два серых вида. Оба они должны отстоять от левой и правой границ вида с контроллером на стандартные расстояния. В частности, должно сохраняться стандартное расстояние между верхним серым видом и верхней границей вышестоящего вида. Между двумя серыми видами по вертикали также должно сохраняться стандартное пространство.
• Нужна кнопка, которая будет вертикально центрирована относительно обоих серых видов.
• Кнопка, расположенная в верхнем сером виде, слева должна быть удалена от края своего вышестоящего вида на стандартное расстояние.
• Левая сторона кнопки, находящейся в нижнем сером виде, должна быть выровнена по правой стороне той кнопки, что находится в верхнем сером виде. Это и есть ограничение для перекрестных видов, которое интересует нас в данном разделе.
• Серые виды должны автоматически изменять размер по мере того, как меняется ориентация вида с контроллером.
• Высота обоих серых видов должна составлять по 100 точек.
Итак, начнем. Чтобы выполнить все перечисленные задачи, вначале обратимся к методу viewDidLoad контроллера вида. Всегда стоит продумывать максимально чистый способ объединения методов. Конечно, в данном примере мы оперируем довольно большим количеством ограничений и видов. Как же нам не захламлять метод viewDidLoad контроллера вида? Вот так:
— (void)viewDidLoad{
[super viewDidLoad];
[self createGrayViews];
[self createButtons];
[self applyConstraintsToTopGrayView];
[self applyConstraintsToButtonOnTopGrayView];
[self applyConstraintsToBottomGrayView];
[self applyConstraintsToButtonOnBottomGrayView];
}
Мы просто распределили стоящие перед нами задачи по разным методам, которые вскоре реализуем. Продолжим — определим виды в файле реализации контроллера вида как расширение интерфейса:
#import «ViewController.h»
@interface ViewController ()
@property (nonatomic, strong) UIView *topGrayView;
@property (nonatomic, strong) UIButton *topButton;
@property (nonatomic, strong) UIView *bottomGrayView;
@property (nonatomic, strong) UIButton *bottomButton;
@end
@implementation ViewController
<# Оставшаяся часть вашего кода находится здесь #>
Далее следует реализовать метод createGrayViews. Как понятно из названия, этот метод отвечает за создание серых видов:
— (UIView *) newGrayView{
UIView *result = [[UIView alloc] init];
result.backgroundColor = [UIColor lightGrayColor];
result.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview: result];
return result;
}
— (void) createGrayViews{
self.topGrayView = [self newGrayView];
self.bottomGrayView = [self newGrayView];
}
Пока несложно? Оба серых вида добавляются к контроллеру нашего вида. Отлично. Что дальше? Теперь нужно реализовать метод createButtons, поскольку он вызывается в методе viewDidLoad контроллера вида. Этот метод должен просто создать кнопки и поместить каждую в ассоциированном с ней сером виде:
— (UIButton *) newButtonPlacedOnView:(UIView *)paramView{
UIButton *result = [UIButton buttonWithType: UIButtonTypeSystem];
result.translatesAutoresizingMaskIntoConstraints = NO;
[result setTitle:@"Button" forState: UIControlStateNormal];
[paramView addSubview: result];
return result;
}
— (void) createButtons{
self.topButton = [self newButtonPlacedOnView: self.topGrayView];
self.bottomButton = [self newButtonPlacedOnView: self.bottomGrayView];
}
Опять же в методе createButtons мы видим, что после создания серых видов и кнопок нужно применить ограничения к этим видам и кнопкам. Начнем с применения ограничений к верхнему серому виду. Эти ограничения должны обеспечивать соблюдение следующих условий:
• верхний вид должен находиться на стандартном расстоянии от вида с контроллером по левому и верхнему краю;
• высота этого серого вида должна составлять 100 точек.
— (void) applyConstraintsToTopGrayView{
NSDictionary *views =
NSDictionaryOfVariableBindings(_topGrayView);
NSMutableArray *constraints = [[NSMutableArray alloc] init];
NSString *const kHConstraint = @"H:|-[_topGrayView]-|";
NSString *const kVConstraint = @"V:|-[_topGrayView(==100)]";
/* Горизонтальные ограничения */
[constraints addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat: kHConstraint
options:0
metrics: nil
views: views]
];
/* Вертикальные ограничения */
[constraints addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat: kVConstraint
options:0
metrics: nil
views: views]
];
[self.topGrayView.superview addConstraints: constraints];
}
Здесь следует остановиться на том, как создается вертикальное ограничение верхнего серого вида. Как видите, мы задаем высоту верхнего вида равной 100 точкам и записываем эту информацию в формате (==100). Среда времени исполнения интерпретирует это значение именно как высоту, поскольку здесь есть указатель V:. Он сообщает среде времени исполнения о следующем: те числа, которые мы сообщаем системе, как-то связаны с высотой и вертикальным выравниванием целевого вида, а не с его шириной и горизонтальным выравниванием.
Далее займемся установкой ограничений для кнопки, находящейся в верхнем сером виде. Это делается с помощью метода applyConstraintsToButtonOnTopGrayView. Кнопка должна будет соответствовать перечисленным далее ограничениям:
• она должна быть вертикально центрирована в верхнем сером виде;
• она должна быть удалена на стандартное расстояние от левого и верхнего края этого серого вида.
У нее не должно быть жестко заданных высоты и ширины; эти значения будут зависеть от содержимого кнопки, в данном случае — от текста Button, который мы решили на ней написать:
— (void) applyConstraintsToButtonOnTopGrayView{
NSDictionary *views = NSDictionaryOfVariableBindings(_topButton);
NSMutableArray *constraints = [[NSMutableArray alloc] init];
NSString *const kHConstraint = @"H:|-[_topButton]";
/* Горизонтальные ограничения */
[constraints addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat: kHConstraint
options:0
metrics: nil
views: views]
];
/* Вертикальные ограничения */
[constraints addObject:
[NSLayoutConstraint constraintWithItem: self.topButton
attribute: NSLayoutAttributeCenterY
relatedBy: NSLayoutRelationEqual
toItem: self.topGrayView
attribute: NSLayoutAttributeCenterY
multiplier:1.0f
constant:0.0f]
];
[self.topButton.superview addConstraints: constraints];
}
Итак, работа с верхним серым видом и находящейся в нем кнопкой завершена. Переходим к нижнему серому виду и его кнопке. Сейчас начнем работать с методом ConstraintsToBottomGrayView. Он будет задавать ограничения для нижнего серого вида. Просто напомню, что для этого вида нам требуется создать следующие ограничения:
• вид удален на стандартное расстояние от верхнего и левого края вышестоящего вида с контроллером;
• вид удален на стандартное расстояние от нижней границы верхнего серого вида;
• высота нижнего серого вида составляет 100 точек.
— (void) applyConstraintsToBottomGrayView{
NSDictionary *views =
NSDictionaryOfVariableBindings(_topGrayView,
_bottomGrayView);
NSMutableArray *constraints = [[NSMutableArray alloc] init];
NSString *const kHConstraint = @"H:|-[_bottomGrayView]-|";
NSString *const kVConstraint =
@"V:|-[_topGrayView]-[_bottomGrayView(==100)]";
/* Горизонтальные ограничения */
[constraints addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat: kHConstraint
options:0
metrics: nil
views: views]
];
/* Вертикальные ограничения */
[constraints addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat: kVConstraint
options:0
metrics: nil
views: views]
];
[self.bottomGrayView.superview addConstraints: constraints];
}
Вертикальные ограничения для нижнего серого вида, выраженные на языке визуального форматирования, выглядят длинновато, но, в сущности, они тривиальны. Приглядевшись к ним повнимательнее, вы заметите, что эти ограничения просто выравнивают верхний и нижний серые виды по сторонам их общего вышестоящего вида с контроллером. При этом используются указатели стандартного расстояния и постоянная высота, равная 100 точкам.
Следующий и, пожалуй, последний компонент пользовательского интерфейса, для которого мы собираемся написать ограничения, — это кнопка, расположенная в нижнем сером виде. Метод, который будет заниматься ее ограничениями, называется applyConstraintsToButtonOnBottomGrayView. Перед тем как его реализовать, обсудим требования, которым должны соответствовать ограничения для нижней кнопки:
• кнопка должна быть вертикально центрирована в нижнем сером виде;
• ее левый край должен быть выровнен по правому краю кнопки, находящейся в верхнем сером виде;
• с ней не должны применяться строго определенные значения высоты и ширины; ее высота и ширина должны зависеть от содержимого — в данном случае от текста Button, который мы на ней записываем.
— (void) applyConstraintsToButtonOnBottomGrayView{
NSDictionary *views = NSDictionaryOfVariableBindings(_topButton,
_bottomButton);
NSString *const kHConstraint = @"H:[_topButton][_bottomButton]";
/* Горизонтальные ограничения */
[self.bottomGrayView.superview addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat: kHConstraint
options:0
metrics: nil
views: views]
];
/* Вертикальные ограничения */
[self.bottomButton.superview addConstraint:
[NSLayoutConstraint constraintWithItem: self.bottomButton
attribute: NSLayoutAttributeCenterY
relatedBy: NSLayoutRelationEqual
toItem: self.bottomGrayView
attribute: NSLayoutAttributeCenterY
multiplier:1.0f
constant:0.0f]
];
}
Наконец, мы должны удостовериться в том, что контроллер вида сообщает среде времени исполнения, что он может обрабатывать любые варианты ориентации. Ведь именно этот аспект наиболее сильно интересовал нас в данном разделе. Поэтому мы переопределим метод supportedInterfaceOrientations в виде UIViewController:
— (NSUInteger) supportedInterfaceOrientations{
return UIInterfaceOrientationMaskAll;
}
Итак, работа с этим контроллером вида завершена. Запустим приложение и посмотрим, как оно работает при книжной ориентации (рис. 3.7).
Рис. 3.7. Приложение отображает компоненты пользовательского интерфейса в книжной ориентации согласно требованиям, которые мы предъявили
А теперь момент истины! Будет ли оно работать в альбомном режиме? Попробуем (рис. 3.8).
Рис. 3.8. Как и ожидалось, тот же самый код отлично работает и при альбомной ориентации экрана
Отлично! Все получилось.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКДанный текст является ознакомительным фрагментом.
Читайте также
Обсуждение
Обсуждение Обычно после того, как пользователь успешно снимет фотографию на устройство с iOS, он ожидает, что этот снимок сохранится в его библиотеке фотографий. Однако приложения, не входящие в стандартный комплект программ iOS, могут запросить пользователя сделать снимок
Обсуждение
Обсуждение Фреймворк Assets Library — удобный посредник между разработчиком и библиотекой фотографий. Как будет указано в разделе 13.6, в iOS SDK вам предоставляются встроенные компоненты графического пользовательского интерфейса, которыми можно пользоваться для доступа к
Обсуждение
Обсуждение Чтобы пользователь мог выбирать фотоснимки или видеоролики из своей библиотеки фотографий, необходимо установить свойство sourceType экземпляра UIImagePickerController в значение UIImagePickerControllerSourceTypePhotoLibrary и только потом открывать перед пользователем инструмент для выбора
Обсуждение
Обсуждение Библиотека ресурсов подразделяется на группы. В каждой группе содержатся ресурсы, а каждый ресурс имеет свойства, например URL (универсальные локаторы ресурсов) и объекты представления.Все ресурсы всех типов можно получать из библиотеки ресурсов с помощью
Обсуждение
Обсуждение Класс UIVideoEditorController, содержащийся в iOS SDK, позволяет программисту вывести на экран перед пользователем специальный интерфейс для редактирования. Все, что требуется сделать, — предоставить URL видеоролика, который предполагается отредактировать, а потом
Обсуждение
Обсуждение В зависимости от того, на работу в какой версии iOS рассчитано ваше приложение, его можно запускать и выполнять на различных устройствах, где установлены разные версии iOS. Например, вы можете разрабатывать приложение в последней версии iOS SDK, но в качестве целевой
Обсуждение
Обсуждение Когда приложение переходит в фоновый режим, работа его основного потока приостанавливается. Потоки, которые вы создаете в своем приложении с помощью метода класса detachNewThreadSelector: toTarget: withObject:, относящегося к классу NSThread, также приостанавливаются. Если вы
Обсуждение
Обсуждение Многие приложения, ежедневно поступающие на рынок App Store, обладают возможностями соединения с теми или иными серверами. Некоторые выбирают с сервера данные для обновления, другие отсылают информацию на сервер и т. д. В течение долгого времени в iOS существовал
Обсуждение
Обсуждение В iOS приложение может запросить продолжить воспроизведение своих аудиофайлов, даже если оно само переходит в фоновый режим. В этом разделе мы воспользуемся плеером AVAudioPlayer, который прост и удобен в обращении. Наша задача — запустить аудиоплеер и воспроизвести
Обсуждение
Обсуждение Когда приложение работает в приоритетном режиме, можно получать от экземпляра CLLocationManager делегатные сообщения, информирующие вас о том, что iOS обнаружила перемещение устройства на новое место. Однако если приложение переходит в фоновый режим и становится
Обсуждение
Обсуждение Допустим, пустое приложение iOS (то есть приложение всего с одним окном, для которого еще не написан код) впервые запускается на устройстве с iOS, поддерживающем работу в многозадачном режиме. Оно запускается именно впервые, а не возвращается из фонового режима в
Обсуждение
Обсуждение При работе с приложениями, которые используют класс NSURLConnection, но, уходя в фоновый режим, не запрашивают у iOS дополнительного времени, обращаться с соединениями не составляет никакого труда. Рассмотрим на примере, как будет действовать асинхронное соединение,
Обсуждение
Обсуждение Пока ваше приложение работает в фоновом режиме, может произойти многое! Например, пользователь может вдруг изменить локализацию устройства с iOS на странице Settings (Настройки) и задать, к примеру, испанский язык вместо английского. Приложения могут
Обсуждение
Обсуждение В приложениях, написанных для iOS, файл пакета настроек может быть предоставлен пользователю для внесения собственных настроек. Эти настройки будут доступны пользователю в приложении (Settings) на устройстве. Чтобы лучше понять, как работает этот механизм,
Обсуждение
Обсуждение Пуш-уведомления похожи на локальные уведомления тем, что позволяют сообщать пользователю определенную информацию, даже если ваше приложение неактивно при поступлении уведомления. В то время как локальные уведомления назначаются самим приложением,
Нахавандипур Вандад
Просмотр ограничен
Смотрите доступные для ознакомления главы 👉