Uno.MvvmCross/MvvmCross.Plugins/Sidebar/Views/MvxSidebarViewController.cs

253 строки
8.9 KiB
C#

using System;
using System.Linq;
using System.Reflection;
using MvvmCross.Core.ViewModels;
using MvvmCross.iOS.Support.XamarinSidebar.Extensions;
using MvvmCross.iOS.Views;
using MvvmCross.iOS.Views.Presenters;
using MvvmCross.Platform;
using MvvmCross.Platform.Platform;
using SidebarNavigation;
using UIKit;
namespace MvvmCross.iOS.Support.XamarinSidebar.Views
{
public class MvxSidebarViewController : UIViewController, IMvxSidebarViewController
{
private readonly UIViewController _subRootViewController;
private bool _menuSetupSet;
public MvxSidebarViewController()
{
_subRootViewController = new UIViewController();
}
public void SetNavigationController(UINavigationController navigationController)
{
NavigationController = navigationController;
}
public bool StatusBarHidden { get; set; }
public bool ToggleStatusBarHiddenOnOpen { get; set; } = false;
public new UINavigationController NavigationController { get; private set; }
public SidebarController LeftSidebarController { get; private set; }
public SidebarController RightSidebarController { get; private set; }
public bool HasLeftMenu
{
get
{
if (!_menuSetupSet)
{
SetupSideMenu();
_menuSetupSet = true;
}
return LeftSidebarController != null && LeftSidebarController.MenuAreaController != null;
}
}
public bool HasRightMenu
{
get
{
if (!_menuSetupSet)
{
SetupSideMenu();
_menuSetupSet = true;
}
return RightSidebarController != null && RightSidebarController.MenuAreaController != null;
}
}
protected virtual void SetupSideMenu()
{
var leftSideMenu = ResolveSideMenu(MvxPanelEnum.Left);
var rightSideMenu = ResolveSideMenu(MvxPanelEnum.Right);
if (leftSideMenu == null && rightSideMenu == null)
{
Mvx.Trace(MvxTraceLevel.Warning, $"No sidemenu found. To use a sidemenu decorate the viewcontroller class with the 'MvxPanelPresentationAttribute' class and set the panel to 'Left' or 'Right'.");
AttachNavigationController();
return;
}
if (leftSideMenu != null && rightSideMenu != null)
{
LeftSidebarController = new SidebarController(_subRootViewController, NavigationController, leftSideMenu);
ConfigureSideMenu(LeftSidebarController);
RightSidebarController = new SidebarController(this, _subRootViewController, rightSideMenu);
ConfigureSideMenu(RightSidebarController);
}
else if (leftSideMenu != null)
{
LeftSidebarController = new SidebarController(this, NavigationController, leftSideMenu);
RightSidebarController = null;
ConfigureSideMenu(LeftSidebarController);
}
else if (rightSideMenu != null)
{
LeftSidebarController = null;
RightSidebarController = new SidebarController(this, NavigationController, rightSideMenu);
ConfigureSideMenu(RightSidebarController);
}
}
protected virtual void AttachNavigationController()
{
AddChildViewController(NavigationController);
View.AddSubview(NavigationController.View);
}
protected virtual UIViewController ResolveSideMenu(MvxPanelEnum location)
{
var assembly = Assembly.GetEntryAssembly();
var types = (from type in assembly.GetTypes()
from attribute in type.GetCustomAttributes<MvxSidebarPresentationAttribute>(true)
where attribute.Panel == location
select type).ToArray();
if (types == null || types.Length == 0)
{
return null;
}
if (types != null && types.Length > 1)
{
Mvx.Trace(MvxTraceLevel.Warning, $"Found more then one {location.ToString()} panel, using the first one in the array ({types[0].ToString()}).");
}
return CreateInstance(types[0]) as UIViewController;
}
protected virtual IMvxIosView CreateInstance(Type viewControllerType)
{
var viewModelType = GetBaseType(viewControllerType);
var presenter = Mvx.Resolve<IMvxIosViewPresenter>();
return presenter.CreateViewControllerFor(new MvxViewModelRequest(viewModelType, null, null));
}
protected virtual Type GetBaseType(Type type)
{
while (type.BaseType != null)
{
type = type.BaseType;
if (type.IsGenericType)
{
var viewModelType = type.GetGenericArguments().FirstOrDefault(argument => typeof(IMvxViewModel).IsAssignableFrom(argument));
if (viewModelType != null)
{
return viewModelType;
}
}
}
throw new InvalidOperationException("Unable to locate ViewModel type on ViewController.");
}
protected virtual void ConfigureSideMenu(SidebarController sidebarController)
{
if (sidebarController.MenuAreaController is IMvxSidebarMenu mvxSideMenuSettings)
{
sidebarController.DarkOverlayAlpha = mvxSideMenuSettings.DarkOverlayAlpha;
sidebarController.HasDarkOverlay = mvxSideMenuSettings.HasDarkOverlay;
sidebarController.HasShadowing = mvxSideMenuSettings.HasShadowing;
sidebarController.ShadowColor = mvxSideMenuSettings.ShadowColor;
sidebarController.ShadowRadius = mvxSideMenuSettings.ShadowRadius;
sidebarController.ShadowOpacity = mvxSideMenuSettings.ShadowOpacity;
sidebarController.DisablePanGesture = mvxSideMenuSettings.DisablePanGesture;
sidebarController.ReopenOnRotate = mvxSideMenuSettings.ReopenOnRotate;
sidebarController.StateChangeHandler += (object sender, bool isOpen) =>
{
sidebarController.MenuWidth = mvxSideMenuSettings.MenuWidth;
sidebarController.ViewWillAppear(mvxSideMenuSettings.AnimateMenu);
if (isOpen)
{
mvxSideMenuSettings.MenuDidOpen();
}
else
{
mvxSideMenuSettings.MenuDidClose();
}
};
}
}
public override UIStatusBarAnimation PreferredStatusBarUpdateAnimation
{
get
{
return UIStatusBarAnimation.Fade;
}
}
public override bool PrefersStatusBarHidden()
{
return StatusBarHidden;
}
public void ToggleStatusBarStatus()
{
UIView.Animate(0.25,
() =>
{
StatusBarHidden = !StatusBarHidden;
SetNeedsStatusBarAppearanceUpdate();
}
);
}
public void CloseMenu()
{
CloseMenu(LeftSidebarController);
CloseMenu(RightSidebarController);
}
public void Open(MvxPanelEnum panelEnum)
{
if (panelEnum == MvxPanelEnum.Left)
OpenMenu(LeftSidebarController);
else if (panelEnum == MvxPanelEnum.Right)
OpenMenu(RightSidebarController);
}
protected virtual void OpenMenu(SidebarController sidebarController)
{
if (sidebarController != null && !sidebarController.IsOpen)
{
var sidebarMenu = sidebarController.MenuAreaController as IMvxSidebarMenu;
sidebarMenu?.MenuWillOpen();
sidebarController.OpenMenu();
}
}
protected virtual void CloseMenu(SidebarController sidebarController)
{
if (sidebarController != null && sidebarController.IsOpen)
{
var sidebarMenu = sidebarController.MenuAreaController as IMvxSidebarMenu;
sidebarMenu?.MenuWillClose();
sidebarController.CloseMenu();
}
}
public virtual bool CloseChildViewModel(IMvxViewModel viewModel)
{
if (NavigationController.ViewControllers.Count() > 1)
{
NavigationController.PopViewController(true);
return true;
}
return false;
}
}
}