WP TIPS に戻る

Silverlight Toolkit を使わずカスタム Transition をする

サンプルプロジェクト CustomTransition.zip

WP7 で画面遷移時のアニメーションと言えば、Silverlight Toolkit の Transition を使用する方法が、一番簡単で確実です。

詳しくはこちら、TransitionService

しかしながら Silverlight Toolkit にデフォルトで用意されている Transition ではなく、もっと細かく制御した画面遷移をしたい場合もあるかと思います。

画面遷移の方法

Silverlight Toolkit の画面遷移は、 PhoneApplicationFrame クラスを継承した TransitionFrame クラス上で実装され、アニメーションが行われています。

しかしながら Silverlight Toolkit を使用しないでも、PhoneApplicationPage.OnNavigatedTo メソッドで画面を開いたときのアニメーション, OnNavigatingFrom メソッドで画面を閉じるときのアニメーションを実行することで、画面遷移のアニメーションを行うことが可能です。

まず Expression Blend で画面を開くときのアニメーションと、閉じるときのアニメーションを StoryBoard で作成しておきます。

次に画面が開くときのアニメーションは、以下のコードのようにすることで実現できます。

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{          
   // 戻ってきたときのアニメーション
   if (e.NavigationMode == System.Windows.Navigation.NavigationMode.Back)
       this.OpenAnimation.Begin();
   base.OnNavigatedTo(e);
}

次に、閉じるアニメーション(他のページへと遷移するとき) は、少し工夫が必要です。
ページが閉じるとき == OnNavigatingFrom メソッド実行時なので、OnNavigatingFrom 内でアニメーションを実行すれば良いと思いがちですが、これではダメです。
アニメーション実行中に他のページに移動してしまい、結果アニメーションがされなくなります。
以下のコードのように、一度移動要求があったらそれをキャンセルして閉じるアニメーションを開始し、それが終了したときに改めて次のページに移動します。
このようにすることでアニメーション終了までまってから移動するので、正しくアニメーションをすることが可能です。

string nextUri = "";

protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
{
   // まず初回の移動はキャンセルし、閉じるアニメーションをしてから次ページに移動する。
   if ("".Equals(nextUri))
   {
       // この移動はキャンセル
       e.Cancel = true;

       // 次に移動するページ URI を記録しておく
       this.nextUri = e.Uri.ToString();

       // アニメーション終了後移動
       this.CloseAnimation.Completed += (s, arg) =>
       {
           this.NavigationService.Navigate(new Uri(this.nextUri, UriKind.Relative));
       };

       // 終了アニメーションを実行
       this.CloseAnimation.Begin();
       return;
   }

   base.OnNavigatingFrom(e);
}

というわけで Silverlight Toolkit を使用しなくても、画面遷移アニメーションを作成することが可能です。また StoryBoard ベースのアニメーションのため、非常に柔軟性に富んだアニメーションをすることが出来ます。

注意点

大きな注意点が一つあります。

  • 最初のページから次のページへ行く際のアニメーションで、LayoutRoot.Opacity を 100%→0% にする
    として次のページに移動し、そのページから戻ってきた際、最初のページの LayoutRoot.Opacity == 0% のままになっています。
    なので最初のページに戻った際には、LayoutRoot.Opacity を 0%→100% に戻してあげる必要があります。