kamulog

xamarin.formsのネタなど

Xamarin.Forms の TriggerAction を使って Trigger に連動したアニメーションを設定する

この記事は Xamarin Advent Calendar 2019 の 1日目の記事です。

Triggerの機能にいつのまにか EnterActions / ExitActions なるものが実装されていたので試してみました。

docs.microsoft.com

今までの Trigger でできたこと

Triggerにも種類がありますが、ここでは DataTrigger を使う例を紹介していきます。 DataTriggerを使うと、あるデータに対応してプロパティを変更させたりできるので、色を変えたり可視状態を変えたりすることができます。 ただ、シンプルに切り替えるだけなので唐突な変化になってしまいます。

例えば以下のような XAML で、ViewModelのIsActiveの値に応じてOpacityを変更するようなコードを書くと

<Grid Grid.Row="0">
    <BoxView CornerRadius="60" HeightRequest="120" WidthRequest="120" BackgroundColor="Blue" HorizontalOptions="Center" VerticalOptions="Center" Opacity="0">
        <BoxView.Triggers>
            <DataTrigger TargetType="BoxView" Binding="{Binding IsActive.Value}" Value="True">
                <Setter Property="Opacity" Value="1" />
            </DataTrigger>
        </BoxView.Triggers>
    </BoxView>
</Grid>

www.youtube.com

唐突感は否めません。

TriggerAction を使うと

動画のように Trigger を使って対象の View にアニメーションを設定することができます。

www.youtube.com

これだと唐突感はないのでより自然な切り替えの効果を付ける場合に有効です。

実装方法

TriggerAction<T> のサブクラスを作成し

public class MoveTriggerAction:TriggerAction<VisualElement>
{
    public bool IsActive { get; set; }

    protected override void Invoke(VisualElement sender)
    {
        if (IsActive)
        {
            sender.TranslationX = -sender.Width;
            sender.Opacity = 0;

            sender.TranslateTo(0, 0);
            sender.FadeTo(1);
        }
        else
        {
            sender.TranslateTo(sender.Width, 0);
            sender.FadeTo(0);
        }
    }
}

Invoke メソッドの override にアクションの実装を記述します。 プロパティを設定すると使う時にパラメータを渡せるので、ここではOnとOffを区別するためのIsActiveというプロパティを作りました。 TriggerAction<T>のTはより具体的なクラスにしても良いですが、アニメーションの設定だけであれば汎用的に使えるVisualElementにしておくのが良いと思います。

でこれを、XAML で指定します。

<ContentPage ...
    xmlns:local="clr-namespace:Sample.Triggers"
    ...>
<Grid Grid.Row="0">
    <BoxView CornerRadius="60" HeightRequest="120" WidthRequest="120" BackgroundColor="Blue" HorizontalOptions="Center" VerticalOptions="Center" Opacity="0">
        <BoxView.Triggers>
            <DataTrigger TargetType="BoxView" Binding="{Binding IsActive.Value}" Value="True">
                <DataTrigger.EnterActions>
                    <local:MoveTriggerAction IsActive="True" />
                </DataTrigger.EnterActions>
                <DataTrigger.ExitActions>
                    <local:MoveTriggerAction IsActive="False" />
                </DataTrigger.ExitActions>
            </DataTrigger>
        </BoxView.Triggers>
    </BoxView>
</Grid>
...

EnterActions のところに Trigger の条件を満たした時のアクションを、ExitActionsのところに条件を満たさなくなった時のアクションを指定します。ここには複数のアクションを指定できるようです。

まとめ

TriggerAction を使うことで、Triggerきっかけでアニメーションを設定できるようになりました。 今までTriggerだけだとフワッと表示させたり消したりすることができませんでしたが、これで結構簡単にできるようになりました。地味に便利な機能かと思います。 記事で紹介した DataTrigger 以外のどのTriggerでも使えますのでぜひ使ってみてください。

今回のサンプル

github.com