Skip to content

Commit

Permalink
Add attribute to show page on iOS (#3339)
Browse files Browse the repository at this point in the history
* Add attribute to show page on iOS

* Fixed some small issues in iOS

* Adjusted the implementation for TvOs

* Added all the views and viewmodels for the ios sample

* Updated the page views

* Added all the views to the storyboard, added the right viewmodels and updated the presenters

* Updated the MvxPageViewController, so we now hold a list of pages in there so we can show them correctly
  • Loading branch information
martijn00 authored and Cheesebaron committed May 6, 2019
1 parent 5cc690c commit 8382e53
Show file tree
Hide file tree
Showing 28 changed files with 959 additions and 266 deletions.
@@ -0,0 +1,14 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MS-PL license.
// See the LICENSE file in the project root for more information.

using MvvmCross.Presenters.Attributes;

namespace MvvmCross.Platforms.Ios.Presenters.Attributes
{
public class MvxPagePresentationAttribute : MvxBasePresentationAttribute
{
public static bool DefaultWrapInNavigationController = false;
public bool WrapInNavigationController { get; set; } = DefaultWrapInNavigationController;
}
}
55 changes: 55 additions & 0 deletions MvvmCross/Platforms/Ios/Presenters/MvxIosViewPresenter.cs
Expand Up @@ -30,6 +30,8 @@ public class MvxIosViewPresenter : MvxAttributeViewPresenter, IMvxIosViewPresent

public IMvxTabBarViewController TabBarViewController { get; protected set; }

public IMvxPageViewController PageViewController { get; protected set; }

public IMvxSplitViewController SplitViewController { get; protected set; }

public override MvxBasePresentationAttribute CreatePresentationAttribute(Type viewModelType, Type viewType)
Expand Down Expand Up @@ -109,6 +111,14 @@ public override void RegisterAttributeTypes()
},
CloseTabViewController);

AttributeTypesToActionsDictionary.Register<MvxPagePresentationAttribute>(
(viewType, attribute, request) =>
{
var viewController = (UIViewController)this.CreateViewControllerFor(request);
return ShowPageViewController(viewController, attribute, request);
},
ClosePageViewController);

AttributeTypesToActionsDictionary.Register<MvxModalPresentationAttribute>(
(viewType, attribute, request) =>
{
Expand Down Expand Up @@ -166,6 +176,19 @@ public override void RegisterAttributeTypes()
return true;
}

if (viewController is IMvxPageViewController pageViewController)
{
PageViewController = pageViewController;

// set root
SetupWindowRootNavigation(viewController, attribute);

if (!await CloseModalViewControllers()) return false;
if (!await CloseSplitViewController()) return false;

return true;
}

// check if viewController is a SplitViewController
if (viewController is IMvxSplitViewController splitController)
{
Expand Down Expand Up @@ -300,6 +323,30 @@ protected void SetupWindowRootNavigation(UIViewController viewController, MvxRoo
return Task.FromResult(true);
}

protected virtual Task<bool> ShowPageViewController(
UIViewController viewController,
MvxPagePresentationAttribute attribute,
MvxViewModelRequest request)
{
if (PageViewController == null)
throw new MvxException("Trying to show a page without a PageViewController, this is not possible!");

/*if (viewController is IMvxTabBarItemViewController tabBarItem)
{
attribute.TabName = tabBarItem.TabName;
attribute.TabIconName = tabBarItem.TabIconName;
attribute.TabSelectedIconName = tabBarItem.TabSelectedIconName;
}*/

if (attribute.WrapInNavigationController)
viewController = CreateNavigationController(viewController);

PageViewController.AddPage(
viewController,
attribute);
return Task.FromResult(true);
}

protected virtual Task<bool> ShowModalViewController(
UIViewController viewController,
MvxModalPresentationAttribute attribute,
Expand Down Expand Up @@ -393,6 +440,14 @@ protected virtual Task<bool> CloseTabViewController(IMvxViewModel viewModel, Mvx
return Task.FromResult(false);
}

protected virtual Task<bool> ClosePageViewController(IMvxViewModel viewModel, MvxPagePresentationAttribute attribute)
{
if (PageViewController != null && PageViewController.RemovePage(viewModel))
return Task.FromResult(true);

return Task.FromResult(false);
}

protected virtual Task<bool> CloseMasterSplitViewController(IMvxViewModel viewModel, MvxSplitViewPresentationAttribute attribute)
{
if (SplitViewController != null && SplitViewController.CloseChildViewModel(viewModel, attribute))
Expand Down
17 changes: 17 additions & 0 deletions MvvmCross/Platforms/Ios/Views/IMvxPageViewController.cs
@@ -0,0 +1,17 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MS-PL license.
// See the LICENSE file in the project root for more information.

using MvvmCross.Platforms.Ios.Presenters.Attributes;
using MvvmCross.ViewModels;
using UIKit;

namespace MvvmCross.Platforms.Ios.Views
{
public interface IMvxPageViewController
{
void AddPage(UIViewController viewController, MvxPagePresentationAttribute attribute);

bool RemovePage (IMvxViewModel viewModel);
}
}
168 changes: 168 additions & 0 deletions MvvmCross/Platforms/Ios/Views/MvxBasePageViewController.cs
@@ -0,0 +1,168 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MS-PL license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using Foundation;
using MvvmCross.Logging;
using MvvmCross.Binding.BindingContext;
using MvvmCross.Platforms.Ios.Views.Base;
using MvvmCross.ViewModels;
using UIKit;

namespace MvvmCross.Platforms.Ios.Views
{
public class MvxBasePageViewController : MvxEventSourcePageViewController, IMvxIosView
{
public MvxBasePageViewController(UIPageViewControllerTransitionStyle style = UIPageViewControllerTransitionStyle.Scroll, UIPageViewControllerNavigationOrientation navigationOrientation = UIPageViewControllerNavigationOrientation.Horizontal, UIPageViewControllerSpineLocation spineLocation = UIPageViewControllerSpineLocation.None) : base(style, navigationOrientation, spineLocation)
{
this.AdaptForBinding();
}

public MvxBasePageViewController(UIPageViewControllerTransitionStyle style, UIPageViewControllerNavigationOrientation navigationOrientation, UIPageViewControllerSpineLocation spineLocation, float interPageSpacing) : base(style, navigationOrientation, spineLocation, interPageSpacing)
{
this.AdaptForBinding();
}

public MvxBasePageViewController(UIPageViewControllerTransitionStyle style, UIPageViewControllerNavigationOrientation navigationOrientation) : base(style, navigationOrientation)
{
this.AdaptForBinding();
}

public MvxBasePageViewController(NSCoder coder) : base(coder)
{
this.AdaptForBinding();
}

protected MvxBasePageViewController(NSObjectFlag t) : base(t)
{
this.AdaptForBinding();
}

protected internal MvxBasePageViewController(IntPtr handle) : base(handle)
{
this.AdaptForBinding();
}

public MvxBasePageViewController(string nibName, NSBundle bundle) : base(nibName, bundle)
{
this.AdaptForBinding();
}

public MvxBasePageViewController(UIPageViewControllerTransitionStyle style, UIPageViewControllerNavigationOrientation navigationOrientation, NSDictionary options) : base(style, navigationOrientation, options)
{
this.AdaptForBinding();
}
public object DataContext
{
get
{
// special code needed in PageViewController because View is initialized during construction
return BindingContext?.DataContext;
}
set
{
BindingContext.DataContext = value;
}
}

public IMvxViewModel ViewModel
{
get { return DataContext as IMvxViewModel; }
set { DataContext = value; }
}

public MvxViewModelRequest Request { get; set; }

public IMvxBindingContext BindingContext { get; set; }

public override void ViewDidLoad()
{
base.ViewDidLoad();
ViewModel?.ViewCreated();
}

public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
ViewModel?.ViewAppearing();
}

public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
ViewModel?.ViewAppeared();
}

public override void ViewWillDisappear(bool animated)
{
base.ViewWillDisappear(animated);
ViewModel?.ViewDisappearing();
}

public override void ViewDidDisappear(bool animated)
{
base.ViewDidDisappear(animated);
ViewModel?.ViewDisappeared();
}

public override void DidMoveToParentViewController(UIViewController parent)
{
base.DidMoveToParentViewController(parent);
if (parent == null)
ViewModel?.ViewDestroy();
}

public override void PrepareForSegue(UIStoryboardSegue segue, NSObject sender)
{
base.PrepareForSegue(segue, sender);
this.ViewModelRequestForSegue(segue, sender);
}
}

public class MvxBasePageViewController<TViewModel> : MvxPageViewController, IMvxIosView<TViewModel> where TViewModel : class, IMvxViewModel
{
public MvxBasePageViewController()
{
}

public MvxBasePageViewController(NSCoder coder) : base(coder)
{
}

public MvxBasePageViewController(UIPageViewControllerTransitionStyle style, UIPageViewControllerNavigationOrientation navigationOrientation) : base(style, navigationOrientation)
{
}

public MvxBasePageViewController(string nibName, NSBundle bundle) : base(nibName, bundle)
{
}

public MvxBasePageViewController(UIPageViewControllerTransitionStyle style, UIPageViewControllerNavigationOrientation navigationOrientation, UIPageViewControllerSpineLocation spineLocation) : base(style, navigationOrientation, spineLocation)
{
}

public MvxBasePageViewController(UIPageViewControllerTransitionStyle style, UIPageViewControllerNavigationOrientation navigationOrientation, NSDictionary options) : base(style, navigationOrientation, options)
{
}

public MvxBasePageViewController(UIPageViewControllerTransitionStyle style, UIPageViewControllerNavigationOrientation navigationOrientation, UIPageViewControllerSpineLocation spineLocation, float interPageSpacing) : base(style, navigationOrientation, spineLocation, interPageSpacing)
{
}

protected MvxBasePageViewController(NSObjectFlag t) : base(t)
{
}

protected internal MvxBasePageViewController(IntPtr handle) : base(handle)
{
}

public new TViewModel ViewModel
{
get { return (TViewModel)base.ViewModel; }
set { base.ViewModel = value; }
}
}
}

0 comments on commit 8382e53

Please sign in to comment.