個人的なメモ

Tomohiro Suzuki @hiro128_777 のブログです。Microsoft MVP for Developer Technologies 2017- 本ブログと所属組織の公式見解は関係ございません。

Xamarin Mvvm Cross iOSのデフォルトの画面遷移アニメーションを変更する

Xamarin + Mvvm Cross で iOSのデフォルトの画面遷移アニメーションを変更する方法で詰まりましたのでメモしておきます。

Mvvm Crossで画面遷移する場合、MvxNavigatingObjectクラスのShowViewModelメソッドを使います。

Mvvm Cross のソースコードを参照したところ、最終的には下記のように、MvxIosViewPresenterクラスのShowメソッドが呼ばれています。
ここの第2引数にtrueが入っているためアニメーションが有効となっています。

this.MasterNavigationController.PushViewController(viewController, true /*animated*/);

https://github.com/MvvmCross/MvvmCross/blob/f7fcf18d960f578b851837f2aaaeb4d0e3b72364/MvvmCross/iOS/iOS/Views/Presenters/MvxIosViewPresenter.cs

この部分を差換えるには、下記のようにMvxIosViewPresenterを継承したカスタムのPresenterを作成します。
その上で、デフォルトのアニメーションのを無効として、カスタムのアニメーションを設定します。

using Cirrious.CrossCore.Exceptions;
using Cirrious.MvvmCross.Touch.Views.Presenters;
using Cirrious.MvvmCross.Touch.Views;
using UIKit;
using CoreAnimation;

namespace Application.Touch
{
	public class CustomizedAnimationPresenter : MvxTouchViewPresenter
	{
		public CustomizedAnimationPresenter(UIApplicationDelegate applicationDelegate, UIWindow window)
			: base(applicationDelegate, window)
		{
		}

		protected override UINavigationController CreateNavigationController(UIViewController viewController)
		{
			UINavigationController navBar = base.CreateNavigationController(viewController);
			navBar.NavigationBarHidden = true;
			return navBar;
		}

		public override void Show(IMvxTouchView view)
		{
			var viewController = view as UIViewController;
			if (viewController == null)
			{
				throw new MvxException("Passed in IMvxTouchView is not a UIViewController");
			}
			if (this.MasterNavigationController == null)
			{
				this.ShowFirstView(viewController);
			}
			else
			{
				// ここで自分好みのアニメーションを作成する
				var transition = new CATransition();
				transition.Duration = 0.25;
				transition.Type = CAAnimation.TransitionFade;
				transition.TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut);
				// アニメーションを設定する
				this.MasterNavigationController.View.Layer.AddAnimation(transition, null);
				// 自作のアニメーションを設定したので、デフォルトのアニメーションは無効とする。
				this.MasterNavigationController.PushViewController(viewController, false);
			}
		}

	}
}

次に、Setup.csで標準のPresenterを自作のPresenterと差換えます。

using Cirrious.MvvmCross.Touch.Views.Presenters;
using Cirrious.CrossCore.Platform;
using Cirrious.MvvmCross.ViewModels;
using Cirrious.MvvmCross.Touch.Platform;
using Cirrious.MvvmCross.Binding.Touch.Target;
using Cirrious.MvvmCross.Binding.Bindings.Target.Construction ;
using UIKit;

namespace Application.Touch
{
	public class Setup : MvxTouchSetup
	{
		private MvxApplicationDelegate applicationDelegate;
		private UIWindow window; 

		public Setup(MvxApplicationDelegate applicationDelegate, UIWindow window)
			: base(applicationDelegate, window)
		{
			this.applicationDelegate = applicationDelegate;
			this.window = window;
		}

		// 差換え用の自作Presenterを作成
		protected override IMvxTouchViewPresenter CreatePresenter()
		{
			return new CustomizedAnimationPresenter(this.applicationDelegate, this.window);
		} 

	}
}

これで、自作のPresenterと差換えられ、自作のアニメーションで画面遷移できます。

以上です。