Xamarin.Forms の単純なアニメーション

Download Sampleサンプルのダウンロード

ViewExtensions クラスは、単純なアニメーションを構築するために使用できる拡張メソッドを提供します。 この記事では、ViewExtensions クラスを使用してアニメーションを作成およびキャンセルする方法について説明します。

ViewExtensions クラスには、単純なアニメーションを作成するために使用できる次の拡張メソッドが用意されています。

デフォルトでは、各アニメーションには 250 ミリ秒かかります。 ただし、アニメーションを作成するときに、各アニメーションの所要時間を指定できます。

Note

ViewExtensions クラスには、LayoutTo 拡張メソッドが用意されています。 ただし、このメソッドは、レイアウト状態間の遷移 (サイズと位置の変更を含む) をアニメーション化するために、レイアウトで使用することを目的としています。 したがって、Layout サブクラスでのみ使用する必要があります。

ViewExtensions クラスのアニメーション拡張メソッドはすべて非同期であり、Task<bool> オブジェクトを返します。 戻り値は、アニメーションが完了した場合は false、アニメーションが取り消された場合は true です。 そのため、アニメーション メソッドは通常、await 演算子と共に使用する必要があります。これにより、アニメーションがいつ完了したかを簡単に判断できます。 さらに、前のメソッドが完了した後に実行される後続のアニメーション メソッドを使用して、順次アニメーションを作成することが可能になります。 詳細については、「複合アニメーション」を参照してください。

アニメーションをバックグラウンドで完了させる必要がある場合は、await 演算子を省略できます。 このシナリオでは、アニメーション拡張メソッドは、アニメーションを開始後すぐに元に戻り、アニメーションがバックグラウンドで実行されます。 この操作は、複合アニメーションを作成するときに利用できます。 詳細については、「複合アニメーション」を参照してください。

await 演算子の詳細については、「非同期サポートの概要」を参照してください。

単一アニメーション

ViewExtensions 内の各拡張メソッドは、一定期間にわたってプロパティをある値から別の値に段階的に変更する 1 つのアニメーション操作を実装します。 このセクションでは、各アニメーション操作について説明します。

回転

次のコード例は、 RotateTo メソッドを使用して、ImageRotation プロパティをアニメーション化する方法を示しています。

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

このコードは、2 秒 (2,000 ミリ秒) で最大 360 度回転することで、Image インスタンスをアニメーション化します。 RotateTo メソッドは、アニメーションの開始の現在の Rotation プロパティ値を取得し、その値から最初の引数 (360) まで回転します。 アニメーションが完了すると、画像の Rotation プロパティは 0 にリセットされます。 これにより、アニメーション終了後に Rotation プロパティが 360 のままにならず、追加の回転が阻止されます。

次のスクリーンショットは、各プラットフォームで進行中の回転を示しています。

Rotation Animation

Note

RotateTo メソッドに加えて、RotateXTo メソッドと RotateYTo メソッドもあります。これらのメソッドは、RotationX プロパティと RotationY プロパティをそれぞれアニメーション化します。

相対回転

次のコード例では、RelRotateTo メソッドを使用して、ImageRotation プロパティを段階的に増減する方法を示します。

await image.RelRotateTo (360, 2000);

このコードは、開始位置から 2 秒 (2,000 ミリ秒) で 360 度回転することで、Image インスタンスをアニメーション化します。 RelRotateTo メソッドは、アニメーションの開始の現在の Rotation プロパティ値を取得し、その値から最初の引数 (360) を加えた値まで回転します。 これにより、各アニメーションは、常に開始位置から 360 度回転します。 そのため、アニメーションの進行中に新しいアニメーションが呼び出されると、そのアニメーションは現在の位置から開始され、増分値が 360 度ではない位置で終了する可能性があります。

次のスクリーンショットは、各プラットフォームで進行中の相対回転を示しています。

Relative Rotation Animation

スケーリング

次のコード例は、ScaleTo メソッドを使用して、ImageScale プロパティをアニメーション化する方法を示しています。

await image.ScaleTo (2, 2000);

このコードは、2 秒 (2,000 ミリ秒) で最大 2 倍のサイズにスケーリングすることで、Image インスタンスをアニメーション化します。 ScaleTo メソッドは、アニメーションの開始の現在の Scale プロパティ値 (既定値は 1) を取得し、その値から最初の引数 (2) までスケーリングします。 これは、画像のサイズが 2 倍に拡大される効果があります。

次のスクリーンショットは、各プラットフォームで進行中のスケーリングを示しています。

Scaling Animation

Note

ScaleTo メソッドに加えて、ScaleX プロパティと ScaleY プロパティをそれぞれアニメーション化する ScaleXTo メソッドと ScaleYTo メソッドもあります。

相対スケーリング

次のコード例は、RelScaleTo メソッドを使用して、ImageScale プロパティをアニメーション化する方法を示しています。

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 度完全に回転するようになります。

Rotation Animation with Anchors

翻訳

次のコード例では、TranslateTo メソッドを使用して、ImageTranslationX プロパティと TranslationY プロパティをアニメーション化する方法を示します。

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

このコードは、Image インスタンスを 1 秒 (1,000 ミリ秒) にわたって水平方向および垂直方向に移動することによってアニメーション化します。 TranslateTo メソッドは、画像を 100 ピクセル左に、100 ピクセル上に同時に移動します。 これは、1 番目と 2 番目の引数が両方とも負の数であるためです。 正の数値を指定すると、画像が右および下に移動します。

次のスクリーンショットは、各プラットフォームで進行中の移動を示しています。

Translation Animation

Note

要素が最初に画面外に配置され、その後画面上に移動した場合、移動後も要素の入力レイアウトは画面外に残り、ユーザーはそれを操作できません。 そのため、ビューを最終的な位置に配置し、必要な移動を実行することをお勧めします。

フェード

次のコード例は、FadeTo メソッドを使用して、ImageOpacity プロパティをアニメーション化する方法を示しています。

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

このコードは、Image インスタンスを 4 秒 (4,000 ミリ秒) でフェード インしてアニメーション化します。 FadeTo メソッドは、アニメーションの開始の現在の Opacity プロパティ値を取得し、その値から最初の引数 (1) までフェード インします。

次のスクリーンショットは、各プラットフォームで進行中のフェード インを示しています。

Fading Animation

複合アニメーション

複合アニメーションはアニメーションの連続した組み合わせであり、次のコード例に示すように、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 アニメーションが両方とも完了します。

複数の非同期メソッドを同時に実行する

staticTask.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 回転です。 これらの値は素数であるため、回転が同期されることはなく、繰り返しパターンが発生することはありません。

次のスクリーンショットは、各プラットフォームで進行中の複数の回転を示しています。

Composite Animation

アニメーションの取り消し

アプリケーションは、次のコード例に示すように、CancelAnimations 拡張メソッドへの呼び出しを使用して 1 つ以上のアニメーションを取り消すことができます。

image.CancelAnimations();

これにより、 Image インスタンスで現在実行中のすべてのアニメーションが直ちに取り消されます。

まとめ

この記事では、ViewExtensions クラスを使用してアニメーションを作成およびキャンセルする方法について説明しました。 このクラスには、VisualElement インスタンスの回転、スケーリング、転送、フェードを行うシンプルなアニメーションを構築するために使用できる拡張メソッドが備わっています。