[Xamarin.Forms] シンプルなアニメーション(回転、拡大・縮小、移動、フェード)を実行する方法
はじめに
こんにちは。加藤です。
今回は、Xamarin.Formsで回転、拡大・縮小、移動、フェードなどのシンプルなアニメーションを実行する方法について紹介します。
検証環境
以下の環境で動作を確認しています。
- Xamarin Studio Community バージョン 6.2(build 1829)
- Xamarin.Forms バージョン 2.3.3.193
- iPhone 7 iOS 10.2(シミュレーター)
- Nexus 5 Androidバージョン6.0.1(実機)
画面レイアウト
以下のように、一通りのアニメーションを試せるようにボタンを配置しました。アニメーション対象は青いBoxViewとしました。
XAMLは以下のようになっています。各ボタンのイベントハンドラーでにアニメーションロジックを書いていきます。
<?xml version="1.0" encoding="utf-8"?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:AnimationSample" x:Class="AnimationSample.AnimationSamplePage"> <StackLayout Padding="10, 60, 10, 10" Spacing="100"> <BoxView x:Name="boxView" BackgroundColor="Blue" WidthRequest="100" HeightRequest="100" HorizontalOptions="Center" /> <Grid> <Grid.RowDefinitions> <RowDefinition Height="44" /> <RowDefinition Height="44" /> <RowDefinition Height="44" /> <RowDefinition Height="44" /> <RowDefinition Height="44" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Button x:Name="rotationButton" TextColor="White" Text="Rotation" Grid.Row="0" Grid.Column="0" BackgroundColor="Gray" Clicked="RotationButton_Clicked" /> <Button x:Name="relativeRotationButton" TextColor="White" Text="RelativeRotation" Grid.Row="0" Grid.Column="1" BackgroundColor="Gray" Clicked="RelativeRotationButton_Clicked" /> <Button x:Name="scalingButton" TextColor="White" Text="Scaling" Grid.Row="1" Grid.Column="0" BackgroundColor="Gray" Clicked="ScalingButton_Clicked" /> <Button x:Name="relativeScalingButton" TextColor="White" Text="RelativeScaling" Grid.Row="1" Grid.Column="1" BackgroundColor="Gray" Clicked="RelativeScalingButton_Clicked" /> <Button x:Name="translationButton" TextColor="White" Text="Translation" Grid.Row="2" Grid.Column="0" BackgroundColor="Gray" Clicked="TranslationButton_Clicked" /> <Button x:Name="fadingButton" TextColor="White" Text="Fading" Grid.Row="2" Grid.Column="1" BackgroundColor="Gray" Clicked="FadingButton_Clicked" /> <Button x:Name="compoundButton" TextColor="White" Text="Compound" Grid.Row="3" Grid.Column="0" BackgroundColor="Gray" Clicked="CompoundButton_Clicked" /> <Button x:Name="compositeButton" TextColor="White" Text="Composite" Grid.Row="3" Grid.Column="1" BackgroundColor="Gray" Clicked="CompositeButton_Clicked" /> <Button x:Name="resetButton" TextColor="White" Text="Reset" Grid.Row="4" Grid.ColumnSpan="2" BackgroundColor="Gray" Clicked="ResetButton_Clicked" /> </Grid> </StackLayout> </ContentPage>
アニメーションの実装
回転(絶対指定)
回転はRotateTo
メソッドで行います。第1引数に回転の角度(度)、第2引数にアニメーションの時間(ミリ秒)を指定します。
private async void RotationButton_Clicked(object sender, System.EventArgs e) { // 1秒かけて360度になるように回転する。 await boxView.RotateTo(360, 1000); // アニメーション後にRotationを0に戻す。これによって再度ボタンをタップした時にアニメーションが行えるようにする。 boxView.Rotation = 0; }
iOS | Android |
RotateTo
はZ方向を軸に回転しますが、その他にもX方向を軸に回転するRotateXTo
メソッドや、Y方向を軸に回転するRotateYTo
メソッドも用意されています。
回転(相対指定)
上で述べている「絶対指定」とは、「指定した値になるようにアニメーションする」という意味です。
それに対して「相対指定」もあります。これは「現在の値に指定した増減値を加えるアニメーション」です。
相対指定の回転はRelRotateTo
メソッドで行います。引数はRotateTo
メソッドと同じです。
private async void RelativeRotationButton_Clicked(object sender, System.EventArgs e) { // 1秒かけて現在の角度に30度プラスする。 await boxView.RelRotateTo(30, 1000); }
ボタンをタップする度に30度回転しています。
iOS | Android |
拡大・縮小(絶対指定)
拡大縮小はScaleTo
メソッドで行います。第1引数に拡大・縮小の倍率、第2引数にアニメーションの時間(ミリ秒)を指定します。
以下は2倍に拡大する例です。
private async void ScalingButton_Clicked(object sender, System.EventArgs e) { // 1秒かけて2倍に拡大 await boxView.ScaleTo(2, 1000); }
iOS | Android |
拡大・縮小(相対指定)
拡大・縮小にも相対指定のメソッド、RelScaleTo
が用意されています。
private async void RelativeScalingButton_Clicked(object sender, System.EventArgs e) { // 現在のScaleに0.5プラスする。 await boxView.RelScaleTo(0.5, 1000); }
1回のボタンタップでScaleを+0.5しているので、2回ボタンをタップすると元の大きさの2倍になります。
iOS | Android |
移動
移動はTranslateTo
メソッドで行います。第1引数にX方向の移動量、第2引数にY方向の移動量、第3引数にアニメーションの時間(ミリ秒)を指定します。
private async void TranslationButton_Clicked(object sender, System.EventArgs e) { // 1秒かけて右と下に50ずつ移動 await boxView.TranslateTo(50, 50, 1000); }
右と下に同時に移動するので斜めに移動します。
iOS | Android |
フェード
フェードはFadeTo
メソッドで行います。
以下の例では、1秒かけてBoxViewが透明な状態から徐々に表示されていきます。
private async void FadingButton_Clicked(object sender, System.EventArgs e) { // 不透明度の初期値は0(透明) boxView.Opacity = 0; // 1秒かけて不透明度を1にする await boxView.FadeTo(1, 1000); }
iOS | Android |
拡大・縮小や回転の中心を変更する
デフォルトでは拡大・縮小や回転の中心はビューの真ん中なのですが、AnchorX
、AnchorX
プロパティで中心を変更することができます。
以下は、BoxViewの左上を中心に360度回転する例です。
private async void RotationButton_Clicked(object sender, System.EventArgs e) { // ビューの左上を中心にする。 boxView.AnchorX = 0; boxView.AnchorY = 0; // 1秒かけて360度になるように回転する。 await boxView.RotateTo(360, 1000); }
iOS | Android |
複数のアニメーションを組み合わせる
上述したアニメーションを組み合わせることも可能です。
アニメーションをシーケンシャルに1つずつ実行したい
アニメーションを1つずつ順番に実行したい場合はawait
を使用します。これにより前のアニメーションが終わってから次のアニメーションが行われます。
private async void CompoundButton_Clicked(object sender, System.EventArgs e) { await boxView.TranslateTo(50, 50, 500); // 500ミリ秒かけて右下に50移動 await boxView.RelRotateTo(30, 1000); // 1000ミリ秒かけて30度回転 await boxView.ScaleTo(0.5, 2000); // 2000ミリ秒かけて0.5倍の大きさに }
iOS | Android |
単純にアニメーションを同時実行したい
単純にアニメーションを同時実行したい場合はawait
しなければOKです。ただし、この場合アニメーションの完了やキャンセルを感知できないので通常は後述の方法を使った方がよいと思います。
private void CompositeButton_Clicked(object sender, System.EventArgs e) { boxView.TranslateTo(50, 50, 500); boxView.RelRotateTo(30, 1000); boxView.ScaleTo(0.5, 2000); }
同時に開始したアニメーションが1つでも終わったら後続の処理をしたい
この場合はTask.WhenAny
を使います。
Task.WhenAny
は引数にアニメーションのTaskを取ります。
以下の例では3つアニメーションを同時実行していますが、一番時間の短いTranslateTo
のアニメーションが終わるとすぐにWriteLine
が実行されます。
private async void CompositeButton_Clicked(object sender, System.EventArgs e) { // WhenAnyは同時に開始したアニメーションが1つでも終われば完了となる await Task.WhenAny( boxView.TranslateTo(50, 50, 500), boxView.RelRotateTo(30, 1000), boxView.ScaleTo(0.5, 2000) ); WriteLine("finish animation"); }
同時に開始したアニメーションが全て終わったら後続の処理をしたい
この場合はTask.WhenAll
を使います。Task.WhenAny
と同様、引数にアニメーションのTaskを取ります。
private async void CompositeButton_Clicked(object sender, System.EventArgs e) { // WhenAllは同時に開始したアニメーションが全て終われば完了となる await Task.WhenAll( boxView.TranslateTo(50, 50, 500), boxView.RelRotateTo(30, 1000), boxView.ScaleTo(0.5, 2000) ); WriteLine("finish animations."); }
iOS | Android |
アニメーションをキャンセルするには
ViewExtensions.CancelAnimations(対象のビュー)
でアニメーションをキャンセルすることができます。
今回のサンプルだとResetボタンの処理で使っていました。
private void ResetButton_Clicked(object sender, System.EventArgs e) { // アニメーションをキャンセル ViewExtensions.CancelAnimations(boxView); // アニメーションで変更したプロパティをリセット boxView.Rotation = 0; boxView.Scale = 1; boxView.TranslationX = 0; boxView.TranslationY = 0; boxView.Opacity = 1; boxView.AnchorX = 0.5; boxView.AnchorY = 0.5; }
おわりに
今回は、Xamarin.Formsで回転、拡大・縮小、移動、フェードなどのシンプルなアニメーションを実行する方法をご紹介しました。
非常に分かりやすくて使い易いAPIだと思います。