Xamarin.Forms の単純なアニメーション
ViewExtensions クラスは、単純なアニメーションを構築するために使用できる拡張メソッドを提供します。 この記事では、ViewExtensions クラスを使用してアニメーションを作成およびキャンセルする方法について説明します。
ViewExtensions
クラスには、単純なアニメーションを作成するために使用できる次の拡張メソッドが用意されています。
CancelAnimations
はアニメーションを取り消します。FadeTo
は、VisualElement
のOpacity
プロパティをアニメーション化します。RelScaleTo
は、アニメーション化された段階的な増減を、VisualElement
のScale
プロパティに適用します。RotateTo
は、VisualElement
のRotation
プロパティをアニメーション化します。RelRotateTo
は、アニメーション化された段階的な増減を、VisualElement
のRotation
プロパティに適用します。RotateXTo
は、VisualElement
のRotationX
プロパティをアニメーション化します。RotateYTo
は、VisualElement
のRotationY
プロパティをアニメーション化します。ScaleTo
は、VisualElement
のScale
プロパティをアニメーション化します。ScaleXTo
は、VisualElement
のScaleX
プロパティをアニメーション化します。ScaleYTo
は、VisualElement
のScaleY
プロパティをアニメーション化します。TranslateTo
は、VisualElement
のTranslationX
プロパティとTranslationY
プロパティをアニメーション化します。
デフォルトでは、各アニメーションには 250 ミリ秒かかります。 ただし、アニメーションを作成するときに、各アニメーションの所要時間を指定できます。
Note
ViewExtensions
クラスには、LayoutTo
拡張メソッドが用意されています。 ただし、このメソッドは、レイアウト状態間の遷移 (サイズと位置の変更を含む) をアニメーション化するために、レイアウトで使用することを目的としています。 したがって、Layout
サブクラスでのみ使用する必要があります。
ViewExtensions
クラスのアニメーション拡張メソッドはすべて非同期であり、Task<bool>
オブジェクトを返します。 戻り値は、アニメーションが完了した場合は false
、アニメーションが取り消された場合は true
です。 そのため、アニメーション メソッドは通常、await
演算子と共に使用する必要があります。これにより、アニメーションがいつ完了したかを簡単に判断できます。 さらに、前のメソッドが完了した後に実行される後続のアニメーション メソッドを使用して、順次アニメーションを作成することが可能になります。 詳細については、「複合アニメーション」を参照してください。
アニメーションをバックグラウンドで完了させる必要がある場合は、await
演算子を省略できます。 このシナリオでは、アニメーション拡張メソッドは、アニメーションを開始後すぐに元に戻り、アニメーションがバックグラウンドで実行されます。 この操作は、複合アニメーションを作成するときに利用できます。 詳細については、「複合アニメーション」を参照してください。
await
演算子の詳細については、「非同期サポートの概要」を参照してください。
単一アニメーション
ViewExtensions
内の各拡張メソッドは、一定期間にわたってプロパティをある値から別の値に段階的に変更する 1 つのアニメーション操作を実装します。 このセクションでは、各アニメーション操作について説明します。
回転
次のコード例は、 RotateTo
メソッドを使用して、Image
の Rotation
プロパティをアニメーション化する方法を示しています。
await image.RotateTo (360, 2000);
image.Rotation = 0;
このコードは、2 秒 (2,000 ミリ秒) で最大 360 度回転することで、Image
インスタンスをアニメーション化します。 RotateTo
メソッドは、アニメーションの開始の現在の Rotation
プロパティ値を取得し、その値から最初の引数 (360) まで回転します。 アニメーションが完了すると、画像の Rotation
プロパティは 0 にリセットされます。 これにより、アニメーション終了後に Rotation
プロパティが 360 のままにならず、追加の回転が阻止されます。
次のスクリーンショットは、各プラットフォームで進行中の回転を示しています。
Note
RotateTo
メソッドに加えて、RotateXTo
メソッドと RotateYTo
メソッドもあります。これらのメソッドは、RotationX
プロパティと RotationY
プロパティをそれぞれアニメーション化します。
相対回転
次のコード例では、RelRotateTo
メソッドを使用して、Image
の Rotation
プロパティを段階的に増減する方法を示します。
await image.RelRotateTo (360, 2000);
このコードは、開始位置から 2 秒 (2,000 ミリ秒) で 360 度回転することで、Image
インスタンスをアニメーション化します。 RelRotateTo
メソッドは、アニメーションの開始の現在の Rotation
プロパティ値を取得し、その値から最初の引数 (360) を加えた値まで回転します。 これにより、各アニメーションは、常に開始位置から 360 度回転します。 そのため、アニメーションの進行中に新しいアニメーションが呼び出されると、そのアニメーションは現在の位置から開始され、増分値が 360 度ではない位置で終了する可能性があります。
次のスクリーンショットは、各プラットフォームで進行中の相対回転を示しています。
スケーリング
次のコード例は、ScaleTo
メソッドを使用して、Image
の Scale
プロパティをアニメーション化する方法を示しています。
await image.ScaleTo (2, 2000);
このコードは、2 秒 (2,000 ミリ秒) で最大 2 倍のサイズにスケーリングすることで、Image
インスタンスをアニメーション化します。 ScaleTo
メソッドは、アニメーションの開始の現在の Scale
プロパティ値 (既定値は 1) を取得し、その値から最初の引数 (2) までスケーリングします。 これは、画像のサイズが 2 倍に拡大される効果があります。
次のスクリーンショットは、各プラットフォームで進行中のスケーリングを示しています。
相対スケーリング
次のコード例は、RelScaleTo
メソッドを使用して、Image
の Scale
プロパティをアニメーション化する方法を示しています。
await image.RelScaleTo (2, 2000);
このコードは、2 秒 (2,000 ミリ秒) で最大 2 倍のサイズにスケーリングすることで、Image
インスタンスをアニメーション化します。 RelScaleTo
メソッドは、アニメーションの開始の現在の Scale
プロパティ値を取得し、その値から最初の引数 (2) を加えた値までスケーリングします。 これにより、各アニメーションは常に開始位置から 2 倍のスケーリングになります。
アンカーを使用したスケーリングと回転
AnchorX
プロパティと AnchorY
プロパティは、Rotation
プロパティと Scale
プロパティのスケーリングまたは回転の中心を設定します。 そのため、それらの値は RotateTo
メソッドと ScaleTo
メソッドにも影響します。
Image
がレイアウトの中心に配置されている場合、次のコード例は、AnchorY
プロパティを設定して、レイアウトの中心を中心に画像を回転する方法を示しています。
double radius = Math.Min(absoluteLayout.Width, absoluteLayout.Height) / 2;
image.AnchorY = radius / image.Height;
await image.RotateTo(360, 2000);
Image
インスタンスをレイアウトの中心を中心に回転するには、AnchorX
プロパティと AnchorY
プロパティを Image
の幅と高さに相対的な値に設定する必要があります。 この例では、Image
の中心がレイアウトの中心になるように定義されているため、既定の AnchorX
値 0.5 を変更する必要はありません。 ただし、AnchorY
プロパティは、Image
の上部からレイアウトの中心点までの値になるように再定義されます。 これにより、次のスクリーンショットに示すように、Image
がレイアウトの中心点を中心に 360 度完全に回転するようになります。
翻訳
次のコード例では、TranslateTo
メソッドを使用して、Image
の TranslationX
プロパティと TranslationY
プロパティをアニメーション化する方法を示します。
await image.TranslateTo (-100, -100, 1000);
このコードは、Image
インスタンスを 1 秒 (1,000 ミリ秒) にわたって水平方向および垂直方向に移動することによってアニメーション化します。 TranslateTo
メソッドは、画像を 100 ピクセル左に、100 ピクセル上に同時に移動します。 これは、1 番目と 2 番目の引数が両方とも負の数であるためです。 正の数値を指定すると、画像が右および下に移動します。
次のスクリーンショットは、各プラットフォームで進行中の移動を示しています。
Note
要素が最初に画面外に配置され、その後画面上に移動した場合、移動後も要素の入力レイアウトは画面外に残り、ユーザーはそれを操作できません。 そのため、ビューを最終的な位置に配置し、必要な移動を実行することをお勧めします。
フェード
次のコード例は、FadeTo
メソッドを使用して、Image
の Opacity
プロパティをアニメーション化する方法を示しています。
image.Opacity = 0;
await image.FadeTo (1, 4000);
このコードは、Image
インスタンスを 4 秒 (4,000 ミリ秒) でフェード インしてアニメーション化します。 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
この例では、Image
は 6 秒 (6000 ミリ秒) かけて移動します。 Image
の移動では 5 つのアニメーションが使用され、await
演算子は各アニメーションが順番に実行されることを示します。 そのため、後続のアニメーション メソッドは、前のメソッドが完了した後に実行されます。
複合アニメーション
複合アニメーションは、2 つ以上のアニメーションが同時に実行されるアニメーションの組み合わせです。 次のコード例に示すように、待機アニメーションと非待機アニメーションを混在させることで、複合アニメーションを作成できます。
image.RotateTo (360, 4000);
await image.ScaleTo (2, 2000);
await image.ScaleTo (1, 2000);
この例では、Image
はスケーリングされ、4 秒 (4,000 ミリ秒) かけて同時に回転されます。 Image
のスケーリングには、回転と同時に発生する 2 つの連続アニメーションが使用されます。 RotateTo
メソッドは await
演算子なしで実行され、すぐに戻り、最初の ScaleTo
アニメーションが始まります。 最初の ScaleTo
メソッド呼び出しの await
演算子は、最初の ScaleTo
メソッド呼び出しが完了するまで、2 番目の ScaleTo
メソッド呼び出しを遅延させます。 この時点で、RotateTo
アニメーションは半分完了し、 Image
は 180 度回転します。 最後の 2 秒 (2000 ミリ秒) の間に、2 番目の ScaleTo
アニメーションと RotateTo
アニメーションが両方とも完了します。
複数の非同期メソッドを同時に実行する
static
Task.WhenAny
メソッドとTask.WhenAll
メソッドは、複数の非同期メソッドを同時に実行するために使用されるため、複合アニメーションを作成するために使用できます。 どちらのメソッドも Task
オブジェクトを返し、それぞれ Task
オブジェクトを返すメソッドのコレクションを受け入れます。 次のコード例に示すように、Task.WhenAny
メソッドは、そのコレクション内のいずれかのメソッドが実行を完了すると完了します。
await Task.WhenAny<bool>
(
image.RotateTo (360, 4000),
image.ScaleTo (2, 2000)
);
await image.ScaleTo (1, 2000);
この例では、Task.WhenAny
メソッドの呼び出しに 2 つのタスクが含まれています。 最初のタスクは 4 秒 (4,000 ミリ秒) かけて画像を回転させ、2 番目のタスクは 2 秒 (2,000 ミリ秒) かけて画像をスケーリングします。 2 番目のタスクが完了すると、Task.WhenAny
メソッドの呼び出しが完了します。 ただし、RotateTo
メソッドがまだ実行している場合でも、2 番目の 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
メソッドの呼び出しには 3 つのタスクが含まれており、それぞれ 10 分かけて実行されます。 それぞれの Task
は、360 度回転の回数が異なります。RotateTo
は 307 回転、RotateXTo
は 251 回転、RotateYTo
は 199 回転です。 これらの値は素数であるため、回転が同期されることはなく、繰り返しパターンが発生することはありません。
次のスクリーンショットは、各プラットフォームで進行中の複数の回転を示しています。
アニメーションの取り消し
アプリケーションは、次のコード例に示すように、CancelAnimations
拡張メソッドへの呼び出しを使用して 1 つ以上のアニメーションを取り消すことができます。
image.CancelAnimations();
これにより、 Image
インスタンスで現在実行中のすべてのアニメーションが直ちに取り消されます。
まとめ
この記事では、ViewExtensions
クラスを使用してアニメーションを作成およびキャンセルする方法について説明しました。 このクラスには、VisualElement
インスタンスの回転、スケーリング、転送、フェードを行うシンプルなアニメーションを構築するために使用できる拡張メソッドが備わっています。