Сводная информация о главе 22. Анимация

Примечание.

Эта книга была опубликована весной 2016 года и с тех пор не обновлялась. Многое в этой книге остается ценным, но некоторые материалы устарели, а некоторые разделы перестали быть полностью верными или полными.

Вы уже знаете, как создавать собственные анимации с помощью таймера Xamarin.Forms или Task.Delay, но в большинстве случаев проще использовать штатные средства анимации Xamarin.Forms. Анимация реализуется в следующих трех классах:

  • ViewExtensions поддерживает обобщенный подход;
  • Animation дает больше гибкости, но усложняет процесс;
  • AnimationExtension наиболее универсален и работает на самом низком уровне.

Обычно анимация строится на основе свойств, подкрепленных привязываемыми свойствами. Это не обязательно, но только такие свойства динамически реагируют на изменения.

Интерфейс XAML для этих анимаций отсутствует, но вы можете интегрировать анимации в XAML с помощью методов, описанных в главе 23. Триггеры и поведение.

Изучение основных анимаций

Основные функции анимации и методы расширения представлены в классе ViewExtensions. Эти методы применимы только к тем объектам, которые наследуют от VisualElement. Самая простая анимация использует свойства преобразования, описанные в Chapter 21. Transforms.

Пример AnimationTryout демонстрирует применение обработчика событий Clicked из Button для вызова метода расширения RotateTo, чтобы вращать кнопку по кругу.

Метод RotateTo изменяет значение свойства Rotation объекта Button в диапазоне от 0 до 360 градусов за четверть секунды (по умолчанию). При повторном нажатии на Button он ничего не делает, так как свойство Rotation уже имеет значение 360 градусов.

Настройка продолжительности анимации

Второй аргумент RotateTo задает длительность в миллисекундах. Если вы укажете большое значение, нажатие Button в процессе анимации будет запускать новую анимацию с текущего угла.

Относительные анимации

Метод RelRotateTo выполняет относительное вращение, добавляя указанное значение к существующему значению. Этот метод позволяет несколько раз нажимать Button, каждый раз увеличивая значение Rotation на 360 градусов.

Анимации с ожиданием

Все методы анимации в ViewExtensions возвращают объекты Task<bool>. Это означает, что вы можете определить серию последовательных анимаций с помощью ContinueWith или await. При завершении bool возвращается значение false, если анимация не была прервана, или true в случае отмены вызовом метода CancelAnimation, который отменяет запущенную другим методом из ViewExtensions анимацию для того же элемента.

Составные анимации

Вы можете сочетать анимации с ожиданием и без ожидания, чтобы создать составные анимации. В ViewExtensions есть анимации, которые работают со свойствами преобразования TranslationX, TranslationY и Scale.

Обратите внимание, что TranslateTo может влиять одновременно на свойства TranslationX и TranslationY.

Task.WhenAll и Task.WhenAny

Вы также можете управлять несколькими анимациями одновременно, используя Task.WhenAll для получения сигнала о завершении нескольких задач и (или) Task.WhenAny для получения сигнала о завершении первой из нескольких задач.

Вращение и привязка

При вызове методов ScaleTo, RelScaleTo, RotateTo и RelRotateTo вы можете настроить свойства AnchorX и AnchorY, чтобы указать центральную точку для масштабирования и вращения.

Пример CircleButton демонстрирует этот подход, выполняя вращение Button вокруг угла страницы.

Функции для реалистичной анимации

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

Суффикс In указывает, что эффект будет применен в начале анимации, Out применяет эффект в конце, а InOut — и в начале, и в конце анимации.

Пример BounceButton демонстрирует применение функций для реалистичной анимации.

Собственные функции для реалистичной анимации

Вы даже можете определить собственные функции для реалистичной анимации, передавая Func<double, double> в конструктор Easing. Также Easing определяет неявное преобразование из Func<double, double> в Easing. Аргумент функции для реалистичной анимации всегда находится в диапазоне от 0 до 1, так как анимация выполняется линейно от начального до конечного положения. Эта функция обычно возвращает значение в диапазоне от 0 до 1, но на короткий момент времени ее значение может выходить за пределы этого диапазона (например, при применении функций SpringIn и SpringOut) или применяться по другим правилам, если вы хорошо их понимаете.

Пример UneasyScale демонстрирует пользовательскую функцию для реалистичной анимации, а в CustomCubicEase вы найдете еще одну.

Пример SwingButton также содержит пользовательскую функцию для реалистичной анимации наряду с методикой изменения свойств AnchorX и AnchorY в пределах последовательности анимаций с вращением.

В библиотеке Xamarin.FormsBook.Toolkit есть класс JiggleButton, который использует пользовательскую функцию для реалистичной анимации "дрожания" кнопки при нажатии. Эта техника демонстрируется в примере JiggleButtonDemo.

Анимации входа

Анимации достаточно часто применяются при первом открытии страницы. Такие анимации удобно запускать из переопределения OnAppearing для страницы. Для них лучше всего настроить в XAML желаемый вид страницы после завершения анимации, а начальный макет и ход анимации выполнить из кода.

Пример FadingEntrance использует метод расширения FadeTo для плавного появления содержимого страницы.

Пример SlidingEntrance использует метод расширения TranslateTo для "вдвигания" содержимого страницы слева и справа.

Пример SwingingEntrance использует метод расширения RotateYTo для анимации свойства RotationY. Можно также использовать метод RotateXTo.

Бесконечные анимации

Противоположный крайний случай — выполнение анимации до тех пор, пока не завершится работа программы Обычно такой вариант применяется для демонстрационных целей.

Пример FadingTextAnimation использует анимацию FadeTo для плавного появления и удаления двух элементов текста.

Пример PalindromeAnimation демонстрирует палиндром, в котором последовательно переворачиваются на 180 отдельные буквы, пока все не окажутся вверх ногами. После этого вся строка отражается на 180 градусов, демонстрируя тот же текст, который был в исходной строке.

Пример CopterAnimation вращает несложный вертолет BoxView, одновременно поворачивая его вокруг центра экрана.

Пример RotatingSpokes вращает лучи BoxView вокруг центра экрана, а затем вращает каждый луч по отдельности, что создает интересные эффекты:

Снимок экрана с тремя изображениями вращающихся лучей

Но постоянное увеличение значения Rotation для элемента может привести к проблемам, как демонстрирует пример RotationBreakdown.

Пример SpinningImage использует RotateTo, RotateXTo и RotateYTo для создания иллюзии вращения растрового изображения в трехмерном пространстве.

Анимация свойства привязки

Остался лишь один метод ViewExtensions, который мы еще не продемонстрировали. Это метод LayoutTo, который, по сути, анимирует свойство только для чтения Bounds, вызывая метод Layout. Этот метод обычно вызывается производными Layout , как описано в главе 26. CustomLayouts.

Метод LayoutTo следует использовать только в исключительных случаях. Программа BouncingBox применяет его для сжатия и растягивания элемента BoxView, когда тот "отскакивает" от краев страницы.

Пример XamagonXuzzle использует LayoutTo для перемещения плиток по принципу классической игры "пятнашки", в которой вместо чисел собирается и разбирается изображение.

Снимок экрана с тремя изображениями Xamarin Xuzzle

Собственные анимации с ожиданием

Пример TryAwaitableAnimation создает анимацию с поддержкой ожидания. Важнейшим здесь является класс TaskTaskCompletionSource, который умеет возвращать из метода объект и информировать о завершении анимации.

Более подробно об анимациях

Система анимаций в Xamarin.Forms может запутать неподготовленного читателя. Помимо класса Easing, в эту систему входят классы ViewExtensions, Animation и AnimationExtension.

Класс ViewExtensions

Вы уже видели пример ViewExtensions. Он определяет девять методов, которые возвращают Task<bool> и CancelAnimations. Семь из этих девяти методов работают со свойствами преобразования. Остальные два — это FadeTo, который изменяет свойство Opacity и LayoutTo, который вызывает метод Layout.

Класс Animation

Класс Animation содержит конструктор с пятью аргументами, которые позволяют определить методы обратного вызова и информирования о завершении, а также параметры самой анимации.

Дочерние анимации можно добавлять с помощью Add, Insert, WithConcurrent и перегрузки WithConcurrent.

После этого объект анимации запускается вызовом метода Commit.

Класс AnimationExtensions

Класс AnimationExtensions содержит в основном методы расширения. Есть несколько версий метода Animate, а общий метод Animate настолько многообразен, что можно обойтись одной этой функцией для абсолютно любой анимации.

Работа с классом Animation

Пример ConcurrentAnimations демонстрирует выполнение нескольких разных анимаций через класс Animation.

Дочерние анимации

Пример ConcurrentAnimations также демонстрирует несколько дочерних анимаций, в которых используются родственные методы Add и Insert.

Выходим за пределы высокоуровневых методов анимации

Пример ConcurrentAnimations также демонстрирует выполнение анимации без использования свойств, с которыми работают методы ViewExtensions. В одном из этих примеров увеличивается ряд периодов, а в другом анимируется свойство BackgroundColor.

Еще немного о собственных методах с поддержкой ожидания

Метод TranslateTo из ViewExtensions не работает с функцией Easing.SpringOut. Он останавливается, когда функция для реалистичной анимации возвращает результат больше 1.

Библиотека Xamarin.FormsBook.Toolkit содержит класс MoreViewExtensions с методами расширения TranslateXTo и TranslateYTo, при вызове которых не возникает эта проблема, а также с методами CancelTranslateXTo и CancelTranslateYTo для отмены выполняемых анимаций.

В примере SpringSlidingEntrance демонстрируется метод TranslateXTo.

Класс MoreExtensions также содержит TranslateXYTo метод расширения, который объединяет преобразование X и Y и CancelTranslateXYTo метод.

Реализация анимации Безье

Есть возможность разработать анимацию, которая перемещает элемент по траектории сплайна Безье. Библиотека Xamarin.FormsBook.Toolkit содержит структуру BezierSpline, которая инкапсулирует сплайн Безье, и перечисление BezierTangent для управления ориентацией.

Класс MoreViewExtensions содержит метод расширения BezierPathTo и метод CancelBezierPathTo.

Пример BezierLoop демонстрирует анимацию перемещения элемента по траектории кривой Безье.

Работа с классом AnimationExtensions

В стандартной коллекции отсутствует анимация цвета. Это связано с тем, что не существует разумного способа интерполировать два значения Color. Можно выполнять такую интерполяцию в координатах RGB-значения, но подход через HSL-значения ничем не хуже.

Поэтому класс MoreViewExtensions в библиотеке Xamarin.FormsBook.Toolkit содержит два метода анимации Color: RgbColorAnimation и HslColorAnimation. (Они дополняются двумя методами отмены: CancelRgbColorAnimation и CancelHslColorAnimation.)

Оба этих метода используют ColorAnimation, который выполняет анимацию путем вызова расширенного универсального метода Animate из AnimationExtensions.

Пример ColorAnimations демонстрирует применение двух типов анимации цвета.

Структурирование анимаций

Иногда бывает удобно выражать анимации в XAML и использовать их совместно с MVVM. Это рассматривается в следующей главе, глава 23. Триггеры и поведение.