Home > Enterprise >  MvvmCross Dialog Presentation for iOS
MvvmCross Dialog Presentation for iOS

Time:11-24

I have an app that I have written that is running fine on Android Platform. I am currently porting it over to iOS and it seems that a basic function is missing in iOS or I don't know how to make it work. I need to be able to pop up a message box from time to time. I use the following code for Android.

My ViewModel is as follows:

public class MessageDialogViewModel : MvxViewModel<string, MessageDialogViewModel.Result>
{
    public class Result
    {
        public Result(bool parm)
        {
            Success = parm;
        }

        public bool Success { get; set; }
    }

    private readonly IMvxNavigationService _navigationService;

    public MessageDialogViewModel(IMvxNavigationService navigationService)
    {
        _navigationService = navigationService;

        CloseCommand = new MvxAsyncCommand(async () => await _navigationService.Close(this, new Result(true)));
    }

    public override System.Threading.Tasks.Task Initialize()
    {
        return base.Initialize();
    }

    public override void Prepare(string parm)
    {
        base.Prepare();
        Message = parm;
    }

    public IMvxAsyncCommand CloseCommand { get; private set; }

    private string _Message;
    public string Message
    {
        get
        {
            return _Message;
        }
        set
        {
            _Message = value;
            RaisePropertyChanged(() => Message);
        }
    }
}

The Layout is as follows:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="10dp"
    android:background="@drawable/borderdoublewidth">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        style="@style/TableHeaderTextView"
        local:MvxBind="Text Message" />
    <LinearLayout
        android:orientation="horizontal"
        android:gravity="right"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="CLOSE"
            style="@style/DialogButton"
            local:MvxBind="Click CloseCommand" />
    </LinearLayout>
</LinearLayout>

The View for Android is this:

[MvxDialogFragmentPresentation]
[Register(nameof(MessageDialogView))]
public class MessageDialogView : MvxDialogFragment<MessageDialogViewModel>
{
    public MessageDialogView()
    {
    }

    protected MessageDialogView(IntPtr javaReference, JniHandleOwnership transfer)
        : base(javaReference, transfer)
    {
    }

    public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        var ignore = base.OnCreateView(inflater, container, savedInstanceState);

        var view = this.BindingInflate(Resource.Layout.MessageDialogView, null);

        return view;
    }
}

This is my goto popup function in all of my Android apps. It is pretty simple. I created an iOS version of the View as follows:

[MvxModalPresentation(WrapInNavigationController = false,
    ModalTransitionStyle = UIModalTransitionStyle.CrossDissolve,
    ModalPresentationStyle = UIModalPresentationStyle.OverFullScreen)]
class MessageDialogView : MvxViewController<MessageDialogViewModel>
{
    public override void ViewDidLoad()
    {
        View.BackgroundColor = UIColor.White;
        base.ViewDidLoad();

        var formView = new UIView();
        formView.BackgroundColor = UIColor.Black;

        var message = new UILabel() { Text = ViewModel.Message };
        formView.Add(message);
        message.TextColor = UIColor.White;
        message.Font = message.Font.WithSize(20f);

        var btnClose = new UIButton(UIButtonType.RoundedRect);
        btnClose.SetTitle("Close", UIControlState.Normal);
        btnClose.Font = btnClose.Font.WithSize(20f);
        btnClose.SetTitleColor(UIColor.Clear.FromHex(0x00D0F7), UIControlState.Normal);
        formView.Add(btnClose);

        var set = this.CreateBindingSet<MessageDialogView, MessageDialogViewModel>();
        set.Bind(btnClose).To(vm => vm.CloseCommand);
        set.Apply();

        View.Add(formView);

        View.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();

        View.AddConstraints(
            formView.AtLeftOf(View),
            formView.AtRightOf(View),
            formView.AtTopOfSafeArea(View),
            formView.AtBottomOf(View)
        );

        formView.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();

        formView.AddConstraints(
            message.AtTopOf(formView, 10f),
            message.WithSameCenterX(formView),

            btnClose.Below(message, 20f),
            btnClose.AtRightOf(formView)

            );

    }
}

This works, but it's not really a popup. It covers the whole screen. I have tried the other options for ModalPresentationStyle, but the dialog acts the same way no matter what. The docs say that the other options only work on iPads and I am developing for an iPhone. I have seen other apps that have a small popup dialog box. I looked at the code here https://prin53.medium.com/pop-up-xamarin-e2d815441a54 and the example works for his particular purpose, but when I tried to make it work with mine, I get an "Assertion" error that is pretty vague for my level. It seems there has to be a way to popup a small dialog without having to jump through so many hoops. Can anyone help?

Thanks, Jim

CodePudding user response:

OK here is what I did. It's a little dirty but it works. Please don't laugh. I created a view that had a clear background and popped up a standard alert from within it. I was able to use the Message property and execute the CloseCommand, so MessageDialogViewModel sees it the same as it does in Android. Here it is:

[MvxModalPresentation(WrapInNavigationController = false,
    ModalTransitionStyle = UIModalTransitionStyle.CrossDissolve,
    ModalPresentationStyle = UIModalPresentationStyle.OverFullScreen)]
class MessageDialogView : MvxViewController<MessageDialogViewModel>
{
    public override void ViewDidAppear(bool animated)
    {
        base.ViewDidAppear(animated);

        View.BackgroundColor = UIColor.Clear;

        var okAlertController = UIAlertController.Create("", ViewModel.Message, UIAlertControllerStyle.Alert);

        okAlertController.AddAction(UIAlertAction.Create("Close", UIAlertActionStyle.Default, (handler) => ViewModel.CloseCommand.ExecuteAsync()));

        PresentViewController(okAlertController, true, null);
    }
}
  • Related