MvvmCross / MvvmCross-Forms

Support for Xamarin.Forms on MvvmCross: The .NET MVVM framework for cross-platform solutions, including Xamarin.iOS, Xamarin.Android, Windows and Mac.
http://mvvmcross.com
6 stars 2 forks source link

iOS picture chooser plugin does not start #30

Open petero-dk opened 8 years ago

petero-dk commented 8 years ago

On iOS the picture chooser plugin does not launch, this is because the picturechooser plugin relies on the PresentModalViewController which just returns false.

I propose that it be changed to:

     _window.RootViewController.PresentViewController(controller, animated, null);
     return true;
LRP-sgravel commented 8 years ago

Yes indeed for Mvvmcross plugins. I would also add a MvxModalPage that the presenter could assess in order to call PushModalAsync when appropriate!

petero-dk commented 8 years ago

What would be a good way to create a MvxModalPage?

LRP-sgravel commented 8 years ago

The class would basically only serve as a "marker". Haven't tested the following but it's the basic idea. There are others ways of doing it but the iOS modal presenter uses this pattern.

class MvxModalPage : ContentPage
{
}
public abstract class MvxFormsPagePresenter
        : MvxViewPresenter
{
        private bool TryShowPage(MvxViewModelRequest request)
        {
            var page = MvxPresenterHelpers.CreatePage(request);
            if (page == null)
                return false;

            var viewModel = MvxPresenterHelpers.LoadViewModel(request);

            var mainPage = _mvxFormsApp.MainPage as NavigationPage;
            page.BindingContext = viewModel;

            if (mainPage == null)
            {
                _mvxFormsApp.MainPage = new NavigationPage(page);
                mainPage = MvxFormsApp.MainPage as NavigationPage;
                CustomPlatformInitialization(mainPage);
            }
            else
            {
                try
                {
                    if (page is MvxModalPage)
                    {
                        mainPage.PushModalAsync(page);
                    }
                    else
                    {
                        // calling this sync blocks UI and never navigates hence code continues regardless here
                        mainPage.PushAsync(page);
                    }
                }
                catch (Exception e)
                {
                    Mvx.Error("Exception pushing {0}: {1}\n{2}", page.GetType(), e.Message, e.StackTrace);
                    return false;
                }
            }

            return true;
        }
}
LRP-sgravel commented 8 years ago

This is my "hackish" version for iOS but this should be adapted to be put in the shared presenter itself. Only PresentModalViewController is platform specific. It only supports 1 modal dialog at this point...

using MvvmCross.Core.ViewModels;
using MvvmCross.Forms.Presenter.Core;
using MvvmCross.Forms.Presenter.iOS;
using UIKit;
using Xamarin.Forms;
using Project.Views;

namespace Project.iOS
{
    public class MvxModalFormsIosPagePresenter : MvxFormsIosPagePresenter
    {
        private UIWindow Window { get; set; }

        public MvxModalFormsIosPagePresenter(UIWindow window, MvxFormsApp app) : base(window, app)
        {
            Window = window;
        }

        public override void Show(MvxViewModelRequest request)
        {
            NavigationPage mainPage = MvxFormsApp.MainPage as NavigationPage;
            var page = MvxPresenterHelpers.CreatePage(request);

            if (page != null && page.GetType().IsSubclassOf(typeof(ModalContentPage)) && mainPage != null)
            {
                page.BindingContext = MvxPresenterHelpers.LoadViewModel(request);;
                mainPage.Navigation.PushModalAsync(page);
            }
            else
            {
                base.Show(request);
            }
        }

        public override bool PresentModalViewController(UIViewController controller, bool animated)
        {
            Window.RootViewController.PresentViewController(controller, animated, null);

            return true;
        }

        public override void ChangePresentation(MvxPresentationHint hint)
        {
            NavigationPage mainPage = MvxFormsApp.MainPage as NavigationPage;

            if (mainPage  != null && hint is MvxClosePresentationHint && mainPage.Navigation.ModalStack.Count > 0)
            {
                mainPage.Navigation.PopModalAsync(true);
            }
            else
            {
                base.ChangePresentation(hint);
            }
        }
    }
}