ПРОГРАММИРОВАНИЕ ПОД IPHONE, IPAD OBJECTIVE-C часть 2

Промежуточная анимация в iOS

 

Мы уже рассматривали способ реализации покадровой анимации, но о промежуточной не было сказано ни слова. В этом уроке я попытаюсь исправить сложившуюся ситуацию. Сначала поговорим о том, что это такое. Вряд ли найдется человек, который используетiOS и не замечает в нем богатый набор анимаций. Практически никакой объект интерфейса не меняет свое положение, размер или прозрачность резко. Это придает приложениям удобность, красоту и юзабилити. Давайте попробуем сделать что-то подобное в нашем приложении.

 

Для начала создадим самый простой проект с шаблона Single View Application и назовем его Animation и изменим файл интерфейса таким образом, чтобы он был похож на картинку в начале этого урока. Этого скудного оформления нам будет достаточно для экспериментов.

 

Теперь перейдем непосредственно к прцессу написания кода. В первую очередь, нам нужно внести изменения в интерфейс класса:

ViewController.h

<code data-result="[object Object]">#import &lt;UIKit/UIKit.h&gt;

@interface ViewController : UIViewController

@property (strong, nonatomic) IBOutlet UILabel *animBody;

- (IBAction)home;
- (IBAction)move;
- (IBAction)resize;
- (IBAction)alpha;

@end</code>

 

Свяжите все методы и объект animBody с объектами интерфейса. Теперь по одному будем писать реализацию класса и разбераться что в них происходит. Начнем с метода move:

 

<code data-result="[object Object]">- (IBAction)move {
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:1.0f];
    [UIView setAnimationCurve:UIViewAnimationCurveLinear];
    animBody.center = CGPointMake(0.0f, 0.0f);
    [UIView commitAnimations];
}</code>

 

Первым параметром в методе beginAnimations является имя анимации. Это произвольная строка, своего рода метка, для того, чтобы потом понять какая анимация выполнилась. Второй параметр — это контекст в котором будет выполняться анимация. Затем следует метод setAnimationDuration, в нем мы устанавливаем продолжительность анимации. В методе setAnimationCurve происходит установка своего рода типа анимации. В нашем примере используется линейный тип, то есть, передвижение объекта будет происходить равномерно на продолжительности всей анимации. Всего доступны четыре типа:

 

  • UIViewAnimationCurveEaseInOut
  • UIViewAnimationCurveEaseIn
  • UIViewAnimationCurveEaseOut
  • UIViewAnimationCurveLinear

 

Поэкспериментируйте с ними.

 

Самое главное проиходит в третьей строке этого метода (animBody.center = CGPointMake(0.0f, 0.0f);). В ней мы присваиваем новое значение положения объекта. К примеру, если в методе move оставить только эту строку — надпись будет менять свое положение на экран. Но это будет мгновенно, как буд-то она телепортировалась. Методом commitAnimations мы непосредственно применяем анимацию.

 

Уверен, вам не терпиться увидеть результат работы. Можете смело запускать проект и наблюдать за плавным перемещением надписи. Вы уже заметили, что надпись не становится на старое место, чтобы это происходило — допишем реализацию метода home:

 

<code data-result="[object Object]">- (IBAction)home {
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:1.0f];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
    animBody.center = self.view.center;
    [UIView commitAnimations];
}</code>

 

Ничего новго в нем мы не добавили, за исключением применения новых кординат надписи. Как я уже говорил, у UIViewController есть один основной UIView вот мы и присваиваем надписи центры этого основного UIView.

 

Все отлично, но у нас осталось не реализовано еще два метода:

 

<code data-result="[object Object]">- (IBAction)resize {
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:1.0f];
    [UIView setAnimationCurve:UIViewAnimationCurveLinear];
    animBody.frame = CGRectMake(animBody.frame.origin.x, 
                                animBody.frame.origin.y, 
                                200.0f, 100.0f);
    [UIView commitAnimations];
}

- (IBAction)alpha {
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:1.0f];
    [UIView setAnimationCurve:UIViewAnimationCurveLinear];
    animBody.alpha = 0.1f;
    [UIView commitAnimations];
}</code>

 

Они отличаются лишь установкой свойст объекта animBody. В свойстве frame мы можем указать не только новый размер, но и положение объекта на экране. А alpha (как вы уже наверняка догадались) управляет прозрачностью объекта.

 

Во время анимации нет ограничения на количество объектов, свойства которых будут подвержены изменениям или на количество свойств. Проще говоря, метод home можно переписать следующим образом:

 

<code data-result="[object Object]">- (IBAction)home {
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:1.0f];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
    animBody.frame = CGRectMake(115.0f, 220.0f, 90.0f, 20.0f);
    animBody.alpha = 1.0f;
    [UIView commitAnimations];
}</code>

 

Часто возникает ситуация, когда по окончанию анимации нужно выполнить какой-то метод, к примеру, другую анимацию:

 

<code data-result="[object Object]">- (IBAction)alpha {
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:1.0f];
    [UIView setAnimationCurve:UIViewAnimationCurveLinear];
    [UIView setAnimationDidStopSelector:@selector(didHideBody)];
    [UIView setAnimationDelegate:self];
    animBody.alpha = 0.1f;
    [UIView commitAnimations];
}

- (void)didHideBody {
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:1.0f];
    [UIView setAnimationCurve:UIViewAnimationCurveLinear];
    animBody.alpha = 1.0f;
    [UIView commitAnimations];
}</code>

 

В этом примере я использовал два метода:

 

  • setAnimationDidStopSelector для установки метода, который выполнится по окончания анимации
  • setAnimationDelegate для установки делегата (объекта в котором находится установленный метод)

 

Красоту работы анимации сложно передать словами. Попробуйте как это работает.

 

Если все ваши анимации по завершению вызывают один и тот же метод — для их распознавания можно использовать вышеупомянутый параметр animationID метода beginAnimations. Но делегат и селектор прийдется установить так же, как я это сделал с анимацией прозрачности. Как это делать я покажу на примере метода move, а вы можете применить этот способ к остальный.

 

<code data-result="[object Object]">- (IBAction)move {
    [UIView beginAnimations:@"Move" context:nil];
    [UIView setAnimationDuration:1.0f];
    [UIView setAnimationCurve:UIViewAnimationCurveLinear];
    [UIView setAnimationDidStopSelector:@selector(animationfinished:finished:context:)];
    [UIView setAnimationDelegate:self];
    animBody.center = CGPointMake(0.0f, 0.0f);
    [UIView commitAnimations];
}

- (void)animationfinished:(NSString *)animationID 
                 finished:(NSNumber*)finished 
                  context:(void *)context 
{
    NSLog(@"%@", animationID);
}</code>

 

В результате, в консоль будет выведено сообщение Move.

 

Это основные методы украшения вашего приложения. Более конкретно можете почитать в документации или интерфейсе класса UIView.