Created
September 23, 2015 22:22
-
-
Save martijn00/6846f5b33ac6036ebfe6 to your computer and use it in GitHub Desktop.
Sidemenu in Xamarin.iOS using MvvmCross
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public partial class AppDelegate : MvxApplicationDelegate | |
{ | |
private UIWindow window; | |
public RootViewController RootViewController { get { return window.RootViewController as RootViewController; } } | |
public override bool FinishedLaunching(UIApplication app, NSDictionary options) | |
{ | |
window = new UIWindow(UIScreen.MainScreen.Bounds); | |
var setup = new Setup(this, window); | |
setup.Initialize(); | |
var startup = Mvx.Resolve<IMvxAppStart>(); | |
startup.Start(); | |
window.MakeKeyAndVisible(); | |
return true; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class CustomPresenter : MvxViewPresenter, IMvxTouchViewPresenter | |
{ | |
private readonly UIApplicationDelegate _applicationDelegate; | |
private readonly UIWindow _window; | |
protected Dictionary<Type, IBaseViewController> ViewControllers; | |
private static bool UserInterfaceIdiomIsPhone | |
{ | |
get { return UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone; } | |
} | |
public Presenter(UIApplicationDelegate applicationDelegate, UIWindow window) | |
{ | |
_applicationDelegate = applicationDelegate; | |
_window = window; | |
ViewControllers = new Dictionary<Type, IBaseViewController>(); | |
} | |
public void Show(UIViewController viewController) | |
{ | |
if (viewController is IMvxModalTouchView) | |
{ | |
PresentModalViewController(viewController, true); | |
return; | |
} | |
// Ask if the current view wants to replace the current RootViewController | |
if (viewController as IBaseViewController != null) | |
{ | |
if ((viewController as IBaseViewController).ParentViewControllerType == null) | |
{ | |
SetRootViewController(viewController); | |
return; | |
} | |
} | |
// Add new views to the screen. | |
if (viewController as IBaseViewController != null) | |
{ | |
Type parentViewControllerType = (viewController as IBaseViewController).ParentViewControllerType; | |
if (parentViewControllerType == typeof(ContainmentNavigationViewController) && | |
_window.RootViewController != null && | |
_window.RootViewController.ModalViewController != null && | |
_window.RootViewController.ModalViewController.GetType() == typeof(PlayerRootViewController) | |
) | |
{ | |
parentViewControllerType = typeof(PlayerRootViewController); | |
} | |
IBaseViewController parentViewController; | |
if (!ViewControllers.ContainsKey(parentViewControllerType)) | |
{ | |
parentViewController = (IBaseViewController)Activator.CreateInstance(parentViewControllerType); | |
} | |
else | |
{ | |
parentViewController = ViewControllers[parentViewControllerType]; | |
} | |
parentViewController.RegisterViewController(viewController as IBaseViewController); | |
// Only show that view if there is not already a modal-view loaded. | |
if ( | |
( | |
(UIApplication.SharedApplication.Delegate as AppDelegate).RootViewController == null || | |
(UIApplication.SharedApplication.Delegate as AppDelegate).RootViewController.PresentedViewController == null | |
) && | |
!parentViewController.IsVisible() | |
) | |
{ | |
Show((UIViewController)parentViewController); | |
} | |
ViewControllers[parentViewControllerType] = parentViewController; | |
// Closes the hamburger-menu, controled by the SidebarController if it still is opened. | |
// TODO: Move this to another place ... maybe by a presentation-hint? | |
(_window.RootViewController as RootViewController).SidebarController.CloseMenu(true); | |
} | |
else if (viewController as MenuViewController != null) | |
{ | |
(_window.RootViewController as RootViewController).SidebarController.OpenMenu(); | |
} | |
else | |
{ | |
throw new NotSupportedException("The ViewModelController '" + viewController + "' has no definied place where it can be shown. Please update either the Presenter or the controller."); | |
} | |
} | |
private void SetRootViewController(UIViewController viewController) | |
{ | |
// If the RootViewController was set, remove all views and clear the ViewControllers stack. | |
if (_window.RootViewController != null) | |
{ | |
foreach (var view in _window.Subviews) | |
view.RemoveFromSuperview(); | |
ViewControllers.Clear(); | |
} | |
// Set the new viewController and view. | |
_window.RootViewController = viewController; | |
viewController.View.Frame = _window.Frame; | |
_window.AddSubview(_window.RootViewController.View); | |
} | |
#region IMvxViewPresenter implementation | |
public override void Show(MvxViewModelRequest request) | |
{ | |
IMvxTouchView viewController = Mvx.Resolve<IMvxTouchViewCreator>().CreateView(request); | |
Show(viewController as UIViewController); | |
} | |
public override void ChangePresentation(MvxPresentationHint hint) | |
{ | |
if (hint is NavigationRootChangedHint && _window.RootViewController as RootViewController != null) | |
{ | |
// Tell that this is the next "current" item in the menu. | |
((MenuViewController)(_window.RootViewController as RootViewController).SidebarController.MenuAreaController).SetCurrent(((NavigationRootChangedHint)hint).ViewModel); | |
} | |
if (hint is MenuClickedHint) | |
{ | |
// Clear the navigation-stack ... When logging out, this is automatically done by replacing the RootViewController. | |
if (ViewControllers.ContainsKey(typeof(ContainmentNavigationViewController))) | |
{ | |
var navigationController = (ViewControllers[typeof(ContainmentNavigationViewController)] as UINavigationController); | |
navigationController.ViewControllers = new UIViewController[0]; | |
} | |
if (ViewControllers.ContainsKey(typeof(PlayerRootViewController))) | |
{ | |
var navigationController = (ViewControllers[typeof(PlayerRootViewController)] as UINavigationController); | |
navigationController.ViewControllers = new UIViewController[0]; | |
} | |
} | |
else if (hint is MvxClosePresentationHint) | |
{ | |
// Create a request and get the | |
var request = new MvxViewModelRequest((hint as MvxClosePresentationHint).ViewModelToClose.GetType(), null, null, null); | |
IBaseViewController viewControllerToClose = Mvx.GetSingleton<IMvxTouchViewCreator>().CreateView(request) as IBaseViewController; | |
bool closed = false; | |
if (viewControllerToClose != null) | |
{ | |
// The parent of the viewController is most likely the one, holding the navigation stack. | |
var parentViewControllerType = viewControllerToClose.ParentViewControllerType; | |
// If there is a modal-view, it's most likely, that this view is up on the players navigation stack. | |
if (parentViewControllerType == typeof(ContainmentNavigationViewController) && | |
_window.RootViewController != null && | |
_window.RootViewController.ModalViewController != null && | |
_window.RootViewController.ModalViewController.GetType() == typeof(PlayerRootViewController) | |
) | |
{ | |
parentViewControllerType = typeof(PlayerRootViewController); | |
} | |
if (ViewControllers.ContainsKey(parentViewControllerType)) | |
{ | |
var navigationController = ViewControllers[parentViewControllerType] as UINavigationController; | |
if (navigationController != null) | |
{ | |
closed = true; | |
navigationController.PopViewController(true); | |
} | |
} | |
} | |
if (!closed) | |
{ | |
// Please implement a close mechanism ... | |
throw new NotImplementedException(); | |
} | |
} | |
} | |
#endregion IMvxViewPresenter implementation | |
#region IMvxTouchModalHost implementation | |
public bool PresentModalViewController(UIViewController controller, bool animated) | |
{ | |
_window.RootViewController.PresentModalViewController(controller, animated); | |
// Add swipe-down gesture to all modal ViewControllers, since you expect, that you can move them downwards, the direction they came from. | |
UISwipeGestureRecognizer recognizer = new UISwipeGestureRecognizer(() => | |
{ | |
(UIApplication.SharedApplication.Delegate as AppDelegate).RootViewController.DismissModalViewController(true); | |
}); | |
recognizer.Direction = UISwipeGestureRecognizerDirection.Down; | |
controller.View.AddGestureRecognizer(recognizer); | |
return true; | |
} | |
public void NativeModalViewControllerDisappearedOnItsOwn() | |
{ | |
// ignored | |
} | |
#endregion IMvxTouchModalHost implementation | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Setup : MvxTouchSetup | |
{ | |
public Setup(MvxApplicationDelegate appDelegate, UIWindow window) | |
: base(appDelegate, window) | |
{ | |
} | |
protected override IMvxTouchViewPresenter CreatePresenter() | |
{ | |
return new CustomPresenter((MvxApplicationDelegate)ApplicationDelegate, Window); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment