CustomFragment in MVVMCross

人走茶凉 提交于 2019-12-12 04:10:10

问题


I have used the following template in my Android application which has navigation drawer has a list of options such as Settings.

https://github.com/MvvmCross/MvvmCross-Samples/tree/master/XPlatformMenus

Source code could be downloaded from the following url https://github.com/MvvmCross/MvvmCross-Samples

I wonder how could I able to make Settings page as a Dialog or CustomFragment which will look like similar to following image.


回答1:


One approach that you could make use of is to create a custom implementation of Dialog. Following the XPlatformMenus sample you linked to, you could implement something as follows:

Generic Custom Dialog

This class inherits android Dialog control, and can be used with any XML/AXML layout you want. You could tightly couple it to a particular ViewModel/Layout or you can make it handle a generic ViewModel type. Here is an example of the generic type:

public class CustomDialog : Dialog, IMvxBindingContextOwner
{
    public CustomDialog(Context context, int layout, IMvxViewModel viewModel)
        : this(context, Resource.Style.CustomDialog)
    {
        this.BindingContext = new MvxAndroidBindingContext(context, (context as IMvxLayoutInflaterHolder));
        ViewModel = viewModel;
        Init(layout);
    }

    public CustomDialog(Context context, int themeResId)
        : base(context, themeResId)
    {
    }

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

    protected CustomDialog(Context context, bool cancelable, IDialogInterfaceOnCancelListener cancelListener)
        : base(context, cancelable, cancelListener)
    {
    }

    protected CustomDialog(Context context, bool cancelable, EventHandler cancelHandler)
        : base(context, cancelable, cancelHandler)
    {
    }

    private void Init(int layout)
    {
        SetContentView(layout);
    }

    public override void SetContentView(int layoutResID)
    {
        var view = this.BindingInflate(layoutResID, null);
        base.SetContentView(view);
    }

    public IMvxBindingContext BindingContext { get; set; }

    public object DataContext
    {
        get { return this.BindingContext.DataContext; }
        set { this.BindingContext.DataContext = value; }
    }

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

XML layout for modal:

<?xml version="1.0" encoding="utf-8" ?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/colorPrimary">

    <Button
        android:id="@+id/btn_option"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Show"
        local:MvxBind="Click ShowSettingsCommand"/>

    <Button
        android:id="@+id/btn_close"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/btn_option"
        android:text="CLOSE"
        local:MvxBind="Click ShowCloseCommand"/>
</RelativeLayout>

CustomDialog style:

<resources>
  <style name="CustomDialog">
    <item name="android:windowIsFloating">true</item>
    <item name="android:windowNoTitle">true</item>
  </style>
</resources>

Custom Presenter

Create a custom presenter to handle the navigation to show/hide the dialog:

public class CustomPresenter : MvxFragmentsPresenter
{
    protected IMvxViewModelLoader MvxViewModelLoader => Mvx.Resolve<IMvxViewModelLoader>();

    CustomDialog _modal;

    public CustomPresenter(IEnumerable<Assembly> AndroidViewAssemblies) : base(AndroidViewAssemblies)
    {
    }

    protected override void ShowActivity(MvxViewModelRequest request, MvxViewModelRequest fragmentRequest = null)
    {
        if (!Intercept(request))
            base.ShowActivity(request, fragmentRequest);
    }

    protected override void ShowFragment(MvxViewModelRequest request)
    {
        if (!Intercept(request))
            base.ShowFragment(request);
    }

    private bool Intercept(MvxViewModelRequest request)
    {
        if (request.ViewModelType == typeof(ThirdViewModel))
        {
            var activity = Mvx.Resolve<IMvxAndroidCurrentTopActivity>().Activity;
            var viewModel = MvxViewModelLoader.LoadViewModel(request, null) as ThirdViewModel;
            _modal = new CustomDialog(activity, Resource.Layout.modal_popup, viewModel);
            _modal.Show();
            return true;
        }

        if (_modal != null)
        {
            _modal.Dismiss();
            _modal = null;
        }
        return false;
    }
}

Register your custom presenter in the setup class:

protected override IMvxAndroidViewPresenter CreateViewPresenter()
{
    var mvxFragmentsPresenter = new CustomPresenter(AndroidViewAssemblies);
    Mvx.RegisterSingleton<IMvxAndroidViewPresenter>(mvxFragmentsPresenter);
    return mvxFragmentsPresenter;
}

ViewModel

public class ThirdViewModel : BaseViewModel
{
    private MvxCommand _showSettingsCommand;
    public MvxCommand ShowSettingsCommand =>
        _showSettingsCommand ?? (_showSettingsCommand = new MvxCommand(() => ShowViewModel<HomeViewModel>()));

    private MvxCommand _showCloseCommand;
    public MvxCommand ShowCloseCommand =>
        _showCloseCommand ?? (_showCloseCommand = new MvxCommand(() => ShowViewModel<SettingsViewModel>()));
}


来源:https://stackoverflow.com/questions/37333869/customfragment-in-mvvmcross

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!