Простая анимация в Xamarin.Forms

Автор:

learn.microsoft.com

Класс ViewExtensions предоставляет методы расширения, при использовании которых разработчик может создавать простые анимации. В этой статье мы расскажем о том, как создавать и отменять анимации с помощью класса ViewExtensions.

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

  • CancelAnimations отменяет любую анимацию.
  • FadeTo анимирует свойство Opacity визуального элемента (VisualElement).
  • RelScaleTo применяет анимированное постепенное увеличение или уменьшение свойства Scale визуального элемента.
  • RotateTo анимирует свойство Rotation визуального элемента (VisualElement).
  • RelRotateTo применяет анимированное постепенное увеличение или уменьшение к свойству Rotation визуального элемента (VisualElement).
  • RotateXTo анимирует свойство RotationX визуального элемента (VisualElement).
  • RotateYTo анимирует свойство RotationY визуального элемента (VisualElement).
  • ScaleTo анимирует свойство Scale визуального элемента (VisualElement).
  • ScaleXTo анимирует свойство ScaleX визуального элемента (VisualElement).
  • ScaleYTo анимирует свойство ScaleY визуального элемента (VisualElement).
  • TranslateTo анимирует свойства TranslationX и TranslationY визуального элемента (VisualElement).

По умолчанию каждая анимация занимает 250 миллисекунд. Однако длительность каждой анимации может быть задана при создании анимации.

Примечание. Класс ViewExtensions предоставляет метод расширения LayoutTo. Предполагается, что этот метод должен быть использован макетами для анимации переходов между состояниями макета, которые меняют его размер и положение. Поэтому он должен использоваться только подклассами Layout.

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

Если требуется, чтобы анимация завершилась в фоновом режиме, то оператор await можно не использовать. В этом случае методы расширения анимации будут быстро возвращаться после инициирования анимации, а сама анимация будет происходить в фоновом режиме. Этой операцией можно воспользоваться при создании составных анимаций.

Одиночные анимации

Каждый метод расширения ViewExtensions реализует одну операцию анимации, которая постепенно изменяет свойство от одного значения к другому в течение определенного периода времени. В этом разделе рассматривается каждая операция анимации.

Вращение

Следующий пример кода демонстрирует использование метода RotateTo для анимации свойства Rotation изображения (Image):

await image.RotateTo (360, 2000);
image.Rotation = 0;

Этот код анимирует экземпляр Image, поворачивая его на 360 градусов в течение 2 секунд (2000 миллисекунд). Метод RotateTo получает текущее значение свойства Rotation для начала анимации, а затем вращается от этого значения до своего первого аргумента (360). После завершения анимации свойство Rotation изображения сбрасывается в 0. Это гарантирует, что свойство Rotation не останется на 360 после завершения анимации, что предотвратит дополнительные вращения.

На следующих скриншотах показан процесс вращения на каждой платформе:

Примечание. Помимо метода RotateTo, существуют также методы RotateXTo и RotateYTo, которые анимируют свойства RotationX и RotationY соответственно.

Относительное вращение

Следующий пример кода демонстрирует использование метода RelRotateTo для постепенного увеличения или уменьшения свойства Rotation изображения:

await image.RelRotateTo (360, 2000);

Этот код анимирует экземпляр Image, поворачивая его на 360 градусов относительно начальной позиции в течение 2 секунд (2000 миллисекунд). Метод RelRotateTo получает текущее значение свойства Rotation для начала анимации, а затем поворачивается от этого значения до значения плюс первый аргумент (360). Это гарантирует, что каждая анимация всегда будет вращаться на 360 градусов от начальной позиции. Поэтому, если новая анимация вызывается в процессе, когда одна анимация уже идет, то новая начнется с текущей позиции и может закончиться в позиции, которая не превышает 360 градусов.

На следующих скриншотах показано относительное вращение, выполняемое на каждой платформе:

Масштабирование

Следующий пример кода демонстрирует использование метода ScaleTo для анимации свойства Scale изображения:

await image.ScaleTo (2, 2000);

Этот код анимирует экземпляр Image, увеличивая его размер в два раза в течение 2 секунд (2000 миллисекунд). Метод ScaleTo получает текущее значение свойства Scale (значение по умолчанию 1) для начала анимации, а затем масштабирует от этого значения до своего первого аргумента (2). Это приводит к увеличению размера изображения в два раза.

На следующих скриншотах показан процесс масштабирования на каждой платформе:

Примечание. Помимо метода ScaleTo, существуют также методы ScaleXTo и ScaleYTo, которые анимируют свойства ScaleX и ScaleY соответственно.

Относительное масштабирование

Следующий пример кода демонстрирует использование метода RelScaleTo для анимирования свойства Scale изображения:

await image.RelScaleTo (2, 2000);

Этот код анимирует экземпляр Image, увеличивая его размер в два раза в течение 2 секунд (2000 миллисекунд). Метод RelScaleTo получает текущее значение свойства Scale для начала анимации, а затем масштабирует от этого значения до значения плюс первый аргумент (2). Это гарантирует, что каждая анимация всегда будет масштабироваться на 2 от начальной позиции.

Масштабирование и вращение с помощью якорей

Свойства AnchorX и AnchorY задают центр масштабирования или вращения для свойств Rotation и Scale. Поэтому их значения также влияют на методы RotateTo и ScaleTo.

Если изображение размещено в центре макета, следующий пример кода демонстрирует поворот изображения вокруг центра макета путем установки свойства AnchorY:

double radius = Math.Min(absoluteLayout.Width, absoluteLayout.Height) / 2;
image.AnchorY = radius / image.Height;
await image.RotateTo(360, 2000);

Чтобы повернуть экземпляр изображения вокруг центра макета, свойства AnchorX и AnchorY должны быть установлены в значения, которые относятся к ширине и высоте изображения. В этом примере центр изображения определен как центр макета, поэтому значение AnchorX по умолчанию 0,5 менять не нужно. Однако свойство AnchorY переопределяется как значение от вершины изображения до центральной точки макета. Это обеспечивает полный поворот изображения на 360 градусов вокруг центральной точки макета, как показано на следующих скриншотах:

Перевод

Следующий пример кода демонстрирует использование метода TranslateTo для анимации свойств TranslationX и TranslationY изображения:

await image.TranslateTo (-100, -100, 1000);

Этот код анимирует экземпляр Image, переводя его по горизонтали и вертикали в течение 1 секунды (1000 миллисекунд). Метод TranslateTo одновременно переводит изображение на 100 пикселей влево и на 100 пикселей вверх. Это происходит потому, что первый и второй аргументы являются отрицательными числами. Если указать положительные числа, то изображение будет переведено вправо и вниз.

На следующих скриншотах показан процесс перевода на каждой платформе:

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

Медленное выцветание изображения

Следующий пример кода демонстрирует использование метода FadeTo для анимирования свойства Opacity изображения:

image.Opacity = 0;
await image.FadeTo (1, 4000);

Этот код анимирует экземпляр изображения путем его выцветания в течение 4 секунд (4000 миллисекунд). Метод FadeTo получает текущее значение свойства Opacity для начала анимации, а затем затухает от этого значения до своего первого аргумента (1).

На следующих скриншотах показан процесс затухания на каждой платформе:

Комплексные анимации

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

await image.TranslateTo (-100, 0, 1000);   // Move image left
await image.TranslateTo (-100, -100, 1000); // Move image diagonally up and left
await image.TranslateTo (100, 100, 2000);  // Move image diagonally down and right
await image.TranslateTo (0, 100, 1000);    // Move image left
await image.TranslateTo (0, 0, 1000);      // Move image up

В данном примере перевод изображения выполняется в течение 6 секунд (6000 миллисекунд). При переводе изображения используется пять анимаций, причем оператор await указывает на то, что каждая анимация выполняется последовательно. Поэтому последующие методы анимации выполняются после завершения предыдущего метода.

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

Составная анимация – это комбинация анимаций, в которой две или более анимаций выполняются одновременно. Составные анимации могут быть созданы путем смешивания ожидаемых и не ожидаемых анимаций, как показано в следующем примере кода:

image.RotateTo (360, 4000);
await image.ScaleTo (2, 2000);
await image.ScaleTo (1, 2000);

В этом примере изображение масштабируется и одновременно вращается в течение 4 секунд (4000 миллисекунд). При масштабировании изображения используются две последовательные анимации, которые происходят одновременно с вращением. Метод RotateTo выполняется без оператора ожидания и возвращается немедленно, после чего начинается первая анимация ScaleTo. Оператор ожидания первого вызова метода ScaleTo задерживает второй вызов метода ScaleTo до завершения первого вызова метода ScaleTo. В этот момент анимация RotateTo наполовину завершена, и изображение будет повернуто на 180 градусов. В течение последних 2 секунд (2000 миллисекунд) завершается вторая анимация ScaleTo и анимация RotateTo.

Одновременный запуск нескольких асинхронных методов

Статические методы Task.WhenAny и Task.WhenAll используются для одновременного запуска нескольких асинхронных методов и, следовательно, могут применяться для создания составных анимаций. Оба метода возвращают объект Task и принимают коллекцию методов, каждый из которых возвращает объект Task. Метод Task.WhenAny завершается, когда любой метод из его коллекции завершает выполнение, как показано в следующем примере кода:

await Task.WhenAny
(
 image.RotateTo (360, 4000),
 image.ScaleTo (2, 2000)
);
await image.ScaleTo (1, 2000);

В этом примере вызов метода Task.WhenAny содержит две задачи. Первая задача вращает изображение в течение 4 секунд (4000 миллисекунд), а вторая задача масштабирует изображение в течение 2 секунд (2000 миллисекунд). Когда вторая задача завершается, завершается вызов метода Task.WhenAny. Однако, несмотря на то, что метод RotateTo все еще выполняется, второй метод ScaleTo может быть запущен.

Метод Task.WhenAll завершается, когда все методы в его коллекции завершены, как показано в следующем примере кода:

// 10 minute animation
uint duration = 10 * 60 * 1000;
 
await Task.WhenAll (
 image.RotateTo (307 * 360, duration),
 image.RotateXTo (251 * 360, duration),
 image.RotateYTo (199 * 360, duration)
);

В этом примере вызов метода Task.WhenAll содержит три задачи, каждая из которых выполняется в течение 10 минут. Каждая задача делает разное количество вращений на 360 градусов - 307 вращений для RotateTo, 251 вращение для RotateXTo и 199 вращений для RotateYTo. Эти значения являются простыми числами, что гарантирует, что вращения не будут синхронизированы и, следовательно, не приведут к появлению повторяющихся паттернов.

На следующих скриншотах показаны множественные вращения, выполняемые на каждой платформе:

Отмена анимаций

Приложение может отменить одну или несколько анимаций с помощью вызова метода расширения CancelAnimations, как показано в следующем примере кода:

image.CancelAnimations();

Это немедленно отменит все анимации, которые в данный момент выполняются на экземпляре Image.

Материалы по теме