Обсуждение

Обсуждение

В операционной системе iOS предоставляются различные способы выполнения анимации, среди этих возможностей есть как низкоуровневые, так и сравнительно высокоуровневые. Самый высокий уровень работы в данном случае обеспечивается во фреймворке UIKit, о котором мы также поговорим в этом разделе. В UIKit содержится некоторая низкоуровневая функциональность Core Animation, предоставляемая нам в форме довольно аккуратного API, с которым очень удобно работать.

Работа с анимацией в UIKit начинается с вызова метода класса beginAnimations: context:, относящегося к классу UIView. Первый параметр — это опциональное имя, которое вы можете выбрать для вашей анимации, а второй — опциональный контекст, который можно получить позже для передачи анимационным методам делегатов. Вскоре мы поговорим о них обоих.

После того как вы запустите анимацию с помощью метода beginAnimations: context:, она не начнет происходить, так как для этого потребуется еще вызвать метод класса commitAnimations, относящийся к классу UIView. Вычисления, которые вы производите над объектом-видом между вызовом beginAnimations: context: и commitAnimations (в результате которых этот вид, к примеру, перемещается), будут сопровождаться анимацией только после вызова commitAnimations. Рассмотрим пример.

Как упоминалось в разделе 17.4, я включил в пакет моего приложения рисунок Xcode.png. Это ярлык Xcode, который я нашел в картинках Google (см. рис. 17.9). Теперь в моем контроллере вида (см. введение к этой главе) я хочу поместить этот рисунок в виде с изображением типа UIImageView, а потом переместить этот вид с изображением из верхнего левого угла экрана в нижний правый угол.

Вот как мы решим эту задачу.

1. Откройте. h-файл вашего контроллера вида.

2. Определите экземпляр UIImageView как свойство контроллера вида и назовите его xcodeImageView:

#import «ViewController.h»

@interface ViewController ()

@property (nonatomic, strong) UIImageView *xcodeImageView;

@end

3. Когда вид загрузится, поместите изображение Xcode.png в экземпляр UIImage:

— (void) viewDidLoad{

[super viewDidLoad];

UIImage *xcodeImage = [UIImage imageNamed:@"Xcode.png"];

self.xcodeImageView = [[UIImageView alloc]

initWithImage: xcodeImage];

/* Просто задаем размеры, чтобы изображение уменьшилось. */

[self.xcodeImageView setFrame: CGRectMake(0.0f,

0.0f,

100.0f,

100.0f)];

self.view.backgroundColor = [UIColor whiteColor];

[self.view addSubview: self.xcodeImageView];

}

4. На рис. 17.33 показано, как будет выглядеть вид, когда программа запускается в симуляторе iOS.

Рис. 17.33. Добавление вида с изображением в объект-вид

5. Теперь, когда вид появится на экране в методе экземпляра viewDidAppear: контроллера вида, приступим к исполнению анимационного блока, относящегося к виду с изображением. Эта анимация переместит изображение из исходной точки (в левом верхнем углу) в нижний правый угол. Кроме того, мы убедимся, что анимация произойдет за пятисекундный период:

— (void) viewDidAppear:(BOOL)paramAnimated{

[super viewDidAppear: paramAnimated];

/* Начинаем с верхнего левого угла. */

[self.xcodeImageView setFrame: CGRectMake(0.0f,

0.0f,

100.0f,

100.0f)];

[UIView beginAnimations:@"xcodeImageViewAnimation"

context:(__bridge void *)self.xcodeImageView];

/* Пятисекундная анимация. */

[UIView setAnimationDuration:5.0f];

/* Получаем делегаты анимации. */

[UIView setAnimationDelegate: self];

[UIView setAnimationDidStopSelector:

@selector(imageViewDidStop: finished: context:)];

/* Анимация заканчивается в нижнем правом углу. */

[self.xcodeImageView setFrame: CGRectMake(200.0f,

350.0f,

100.0f,

100.0f)];

[UIView commitAnimations];

}

6. Далее выполните реализацию метода делегата imageViewDidStop: finished: context: для контроллера вида, чтобы он вызывался UIKit по завершении анимации. Это не обязательно, так что для примера я просто зарегистрирую несколько сообщений, демонстрирующих, что метод действительно был вызван. В следующих примерах будет показано, как можно использовать метод для запуска какой-то иной активности в момент окончания анимации:

— (void)imageViewDidStop:(NSString *)paramAnimationID

finished:(NSNumber *)paramFinished

context:(void *)paramContext{

NSLog(@"Animation finished.");

NSLog(@"Animation ID = %@", paramAnimationID);

UIImageView *contextImageView = (__bridge UIImageView *)paramContext;

NSLog(@"Image View = %@", contextImageView);

}

Теперь, запустив приложение, вы заметите, что, как только отобразится вид, изображение, показанное на рис. 17.33, начнет перемещаться в нижний правый угол (рис. 17.34). На это уйдет 5 секунд.

Рис. 17.34. Анимируемое изображение переходит в правый нижний угол экрана

Кроме того, обратив внимание на консоль и дождавшись окончания анимации, вы увидите примерно следующий текст:

Animation finished.

Animation ID = xcodeImageViewAnimation

Image View = <UIImageView: 0x8eaee20;

frame = (220 468; 100 100); opaque = NO;

userInteractionEnabled = NO;

layer = <CALayer: 0x8eaef10>>

А теперь рассмотрим конкретные концепции и разберемся, как именно мы анимировали этот вид с изображением. Далее перечислены важные методы класса, относящиеся к UIView, о которых нужно знать, занимаясь анимацией с UIKit.

• beginAnimations: context: — запускает анимационный блок. Любое анимируемое изменение свойств, которое вы применяете к видам после вызова этого метода класса, будет вступать в силу после выполнения анимации.

• setAnimationDuration: — этот метод задает длительность анимации в секундах.

• setAnimationDelegate: — задает объект, который будет получать сообщения делегатов, касающиеся различных событий, которые могли произойти до, во время или после анимации. Если мы задаем объект делегата, это не означает, что анимационные делегаты немедленно запускаются. Кроме того, вы должны использовать различные методы-установщики, относящиеся к классу, применяя их к объекту вида. Так вы сообщаете UIKit, какие селекторы в вашем объекте-делегате какие делегатные сообщения должны получать.

• setAnimationDidStopSelector: — задает в объекте-делегате метод, который должен быть вызван после завершения анимации. Этот метод должен принимать три параметра в следующем порядке:

1) идентификатор анимации типа NSString: здесь будет содержаться идентификатор анимации, передаваемый с началом анимации методу класса beginAnimations: context:, относящемуся к классу UIView;

2) индикатор «завершения» типа NSNumber: этот параметр содержит в NSNumber логическое значение. Среда времени исполнения устанавливает его в YES, если анимация была остановлена в коде, не успев полностью завершиться. Если это значение равно NO, то это означает, что анимация была без перерывов воспроизведена до самого конца;

3) контекст типа void *: это контекст, который с началом анимации передается методу класса beginAnimations: context:, относящемуся к классу UIView.

• setAnimationWillStartSelector: — задает селектор, который должен быть вызван в объекте делегата перед самым началом анимации. Селектор, передаваемый этому методу класса, должен иметь два параметра в таком порядке:

1) идентификатор анимации типа NSString: среда времени исполнения задает для этого параметра значение идентификатора анимации, передаваемого с началом анимации методу класса beginAnimations: context:, относящемуся к классу UIView;

2) контекст типа void *: это контекст, который с началом анимации был передан методу класса beginAnimations: context:, относящемуся к классу UIView.

• setAnimationDelay: — задает задержку для анимации (в секундах) перед ее началом. Например, если это значение установлено в 3.0f, то анимация будет начинаться через 3 секунды после выполнения этого метода.

• setAnimationRepeatCount: — указывает количество прогонов анимации, которые должны быть выполнены в блоке кода.

Теперь, когда нам известны наиболее полезные методы класса UIView, помогающие анимировать виды, рассмотрим другую анимацию. В этом примере кода я создам два вида с изображениями (в каждом из них будет показано одно и то же изображение), и они появятся на экране в одно и то же время, одно в левом верхнем углу, другое — в правом нижнем (рис. 17.35).

Рис. 17.35. Исходное положение, с которого начинается анимация

В этом примере изображение из верхнего левого угла будет называться image 1, а из правого нижнего — image 2.

Как уже упоминалось, в этом коде мы собираемся создать два изображения, в верхнем левом и правом нижнем углах. Далее image 1 станет двигаться по направлению к image 2 и будет так перемещаться на протяжении 3 секунд, а потом медленно исчезнет. Когда image 1 начнет движение, станет двигаться и image 2 — оно пойдет в верхний левый угол экрана, где изначально находилось изображение image 1. Опять же мы хотим, чтобы анимация изображения image 2 завершилась за 3 секунды и оно медленно исчезло. Когда вы запустите этот код на устройстве или симуляторе iOS, такая анимация будет выглядеть очень классно. Теперь расскажу, как все это запрограммировать.

1. В верхней части. m-файла нашего контроллера вида определим два вида с изображениями:

@interface ViewController ()

@property (nonatomic, strong) UIImageView *xcodeImageView1;

@property (nonatomic, strong) UIImageView *xcodeImageView2;

@end

@implementation ViewController

2. В методе экземпляра viewDidLoad, относящемся к контроллеру вашего вида, инициализируем оба этих вида с изображениями и помещаем их в основной вид:

— (CGRect) bottomRightRect{

CGRect endRect;

endRect.origin.x = self.view.bounds.size.width — 100;

endRect.origin.y = self.view.bounds.size.height — 100;

endRect.size = CGSizeMake(100.0f, 100.0f);

return endRect;

}

— (void) viewDidLoad{

[super viewDidLoad];

UIImage *xcodeImage = [UIImage imageNamed:@"Xcode.png"];

self.xcodeImageView1 = [[UIImageView alloc]

initWithImage: xcodeImage];

self.xcodeImageView2 = [[UIImageView alloc]

initWithImage: xcodeImage];

/* Просто задаем размеры так, чтобы изображения уменьшились. */

[xcodeImageView1 setFrame: CGRectMake(0.0f,

0.0f,

100.0f,

100.0f)];

[self.xcodeImageView2 setFrame: [self bottomRightRect]];

self.view.backgroundColor = [UIColor whiteColor];

[self.view addSubview: self.xcodeImageView1];

[self.view addSubview: self.xcodeImageView2];

}

3. Реализуем для нашего контроллера вида метод экземпляра, который называется startTopLeftImageViewAnimation. Как понятно из названия[12], данный метод будет выполнять анимацию для изображения image 1, перемещая его из верхнего левого угла экрана в нижний правый, а изображение тем временем будет медленно исчезать. Такое исчезновение достигается установкой альфа-значения в 0:

— (void) startTopLeftImageViewAnimation{

/* Начинаем с верхнего левого угла. */

[self.xcodeImageView1 setFrame: CGRectMake(0.0f,

0.0f,

100.0f,

100.0f)];

[self.xcodeImageView1 setAlpha:1.0f];

[UIView beginAnimations:@"xcodeImageView1Animation"

context:(__bridge void *)self.xcodeImageView1];

/* Трехсекундная анимация */

[UIView setAnimationDuration:3.0f];

/* Получаем анимационные делегаты. */

[UIView setAnimationDelegate: self];

[UIView setAnimationDidStopSelector:

@selector(imageViewDidStop: finished: context:)];

/* Заканчиваем в нижнем правом углу. */

[self.xcodeImageView1 setFrame: CGRectMake(220.0f,

350.0f,

100.0f,

100.0f)];

[self.xcodeImageView1 setAlpha:0.0f];

[UIView commitAnimations];

}

4. Когда анимация какого-либо из этих видов остановится, мы удалим данный вид из иерархии родительских видов, так как больше в нем не нуждаемся. Как было показано в методе startTopLeftImageViewAnimation, мы передали селектор делегата методу класса setAnimationDidStopSelector:, относящемуся к классу UIView. Этот селектор будет вызываться после окончания анимации image 1 (как было показано ранее) и image 2 (как мы вскоре увидим). Вот реализация этого селектора делегата:

— (void)imageViewDidStop:(NSString *)paramAnimationID

finished:(NSNumber *)paramFinished

context:(void *)paramContext{

UIImageView *contextImageView = (__bridge UIImageView *)paramContext;

[contextImageView removeFromSuperview];

}

5. Кроме того, нам понадобится метод для анимирования image 2. Между написанием анимационных методов для image 2 и image 1 есть небольшая разница. Я хочу начать анимацию image 2, немного не дожидаясь завершения анимации image 1. Следовательно, если анимация image 1 завершается за 3 секунды, то я начну анимировать image 2 со второй секунды анимации image 1. Таким образом, анимация image 2 начнется еще до того, как изображение image 1 дойдет до нижнего правого угла экрана и исчезнет. Чтобы достичь такого результата, я установлю начало анимации для обоих изображений на одно и то же время, но перед началом анимации image 2 поставлю двухсекундную задержку. Итак, если обе анимации начнутся в час дня, то для изображения image 1 начальным моментом анимации будет 13:00:00, а конечным — 13:00:03. Соответствующие значения image 2 будут равны 13:00:02 и 13:00:05. Вот как будет происходить анимация image 2:

— (void) startBottomRightViewAnimationAfterDelay:(CGFloat)paramDelay{

/* Начинаем с нижнего правого угла. */

[self.xcodeImageView2 setFrame: [self bottomRightRect]];

[self.xcodeImageView2 setAlpha:1.0f];

[UIView beginAnimations:@"xcodeImageView2Animation"

context:(__bridge void *)self.xcodeImageView2];

/* Трехсекундная анимация */

[UIView setAnimationDuration:3.0f];

[UIView setAnimationDelay: paramDelay];

/* Получаем анимационные делегаты. */

[UIView setAnimationDelegate: self];

[UIView setAnimationDidStopSelector:

@selector(imageViewDidStop: finished: context:)];

/* Заканчиваем в верхнем левом углу. */

[self.xcodeImageView2 setFrame: CGRectMake(0.0f,

0.0f,

100.0f,

100.0f)];

[self.xcodeImageView2 setAlpha:0.0f];

[UIView commitAnimations];

}

6. И последнее, но немаловажное замечание. Как только вид отобразится, мы должны запустить методы startTopLeftImageViewAnimation и startBottomRightViewAnimationAfterDelay::

— (void) viewDidAppear:(BOOL)paramAnimated{

[super viewDidAppear: paramAnimated];

[self startTopLeftImageViewAnimation];

[self startBottomRightViewAnimationAfterDelay:2.0f];

}

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

Обсуждение

Из книги iOS. Приемы программирования автора Нахавандипур Вандад

Обсуждение Обычно после того, как пользователь успешно снимет фотографию на устройство с 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) на устройстве. Чтобы лучше понять, как работает этот механизм,


Обсуждение

Из книги автора

Обсуждение Пуш-уведомления похожи на локальные уведомления тем, что позволяют сообщать пользователю определенную информацию, даже если ваше приложение неактивно при поступлении уведомления. В то время как локальные уведомления назначаются самим приложением,