Android fragments 如何在MvvmCross中构建自己的选项卡?

Android fragments 如何在MvvmCross中构建自己的选项卡?,android-fragments,xamarin.android,mvvmcross,Android Fragments,Xamarin.android,Mvvmcross,我正在尝试用MonoDroid和MvvmCross构建我自己的标签 建立我自己的选项卡的原因是,我可以进一步控制它们。我希望它们出现在每个屏幕上,即使它们不在选项卡中,我希望控制某些选项卡上的单击 在页面上加载这两个片段是可以的,但是,当我单击选项卡片段或内容片段上导航到下一个内容片段的按钮时,我会收到错误消息“发生了未处理的异常”。这没有多大帮助 02-06 10:15:13.947 W/dalvikvm( 2040): JNI WARNING: JNI method called with

我正在尝试用MonoDroid和MvvmCross构建我自己的标签

建立我自己的选项卡的原因是,我可以进一步控制它们。我希望它们出现在每个屏幕上,即使它们不在选项卡中,我希望控制某些选项卡上的单击

在页面上加载这两个片段是可以的,但是,当我单击选项卡片段或内容片段上导航到下一个内容片段的按钮时,我会收到错误消息“发生了未处理的异常”。这没有多大帮助

 02-06 10:15:13.947 W/dalvikvm( 2040): JNI WARNING: JNI method called with exception pending
 02-06 10:15:13.947 W/dalvikvm( 2040):              in Lcirrious/mvvmcross/droid/fragging/MvxEventSourceFragmentActivity;.n_startActivityForResult:(Landroid/content/Intent;I)V (NewString)
 In mgmain JNI_OnLoad
 02-06 10:15:13.947 W/dalvikvm( 2040): Pending exception is:
 02-06 10:15:13.947 I/dalvikvm( 2040): android.content.ActivityNotFoundException: Unable to find explicit activity class {frags.droid/frags.droid.views.frags.ChildTwoView}; have you declared this activity in your AndroidManifest.xml?
 02-06 10:15:13.947 I/dalvikvm( 2040):   (raw stack trace not found)
 02-06 10:15:13.947 I/dalvikvm( 2040): "main" prio=5 tid=1 NATIVE
 02-06 10:15:13.947 I/dalvikvm( 2040):   | group="main" sCount=0 dsCount=0 obj=0x41aaf710 self=0x41a96210
 02-06 10:15:13.957 I/dalvikvm( 2040):   | sysTid=2040 nice=0 sched=0/0 cgrp=apps handle=1074675708
 02-06 10:15:13.957 I/dalvikvm( 2040):   | state=R schedstat=( 0 0 0 ) utm=164 stm=41 core=0
 02-06 10:15:13.967 I/dalvikvm( 2040):   #00  pc 000012fe  /system/lib/libcorkscrew.so (unwind_backtrace_thread+29)
 02-06 10:15:13.967 I/dalvikvm( 2040):   #01  pc 0006324e  /system/lib/libdvm.so (dvmDumpNativeStack(DebugOutputTarget const*, int)+33)
 02-06 10:15:13.967 I/dalvikvm( 2040):   #02  pc 000572b8  /system/lib/libdvm.so (dvmDumpThreadEx(DebugOutputTarget const*, Thread*, bool)+395)
 02-06 10:15:13.967 I/dalvikvm( 2040):   #03  pc 00057326  /system/lib/libdvm.so (dvmDumpThread(Thread*, bool)+25)
 02-06 10:15:13.967 I/dalvikvm( 2040):   #04  pc 0003b530  /system/lib/libdvm.so
 02-06 10:15:13.967 I/dalvikvm( 2040):   #05  pc 0003eef2  /system/lib/libdvm.so
 02-06 10:15:13.967 I/dalvikvm( 2040):   at cirrious.mvvmcross.droid.fragging.MvxEventSourceFragmentActivity.n_startActivityForResult(Native Method)
 02-06 10:15:13.967 I/dalvikvm( 2040):   at cirrious.mvvmcross.droid.fragging.MvxEventSourceFragmentActivity.startActivityForResult(MvxEventSourceFragmentActivity.java:110)
 02-06 10:15:13.967 I/dalvikvm( 2040):   at android.app.Activity.startActivity(Activity.java:3661)
 02-06 10:15:13.967 I/dalvikvm( 2040):   at android.app.Activity.startActivity(Activity.java:3629)
 02-06 10:15:13.967 I/dalvikvm( 2040):   at mono.android.view.View_OnClickListenerImplementor.n_onClick(Native Method)
 02-06 10:15:13.967 I/dalvikvm( 2040):   at mono.android.view.View_OnClickListenerImplementor.onClick(View_OnClickListenerImplementor.java:29)
 02-06 10:15:13.967 I/dalvikvm( 2040):   at android.view.View.performClick(View.java:4475)
 02-06 10:15:13.967 I/dalvikvm( 2040):   at android.view.View$PerformClick.run(View.java:18786)
 02-06 10:15:13.967 I/dalvikvm( 2040):   at android.os.Handler.handleCallback(Handler.java:730)
 02-06 10:15:13.967 I/dalvikvm( 2040):   at android.os.Handler.dispatchMessage(Handler.java:92)
 02-06 10:15:13.967 I/dalvikvm( 2040):   at android.os.Looper.loop(Looper.java:137)
 02-06 10:15:13.967 I/dalvikvm( 2040):   at android.app.ActivityThread.main(ActivityThread.java:5419)
 02-06 10:15:13.967 I/dalvikvm( 2040):   at java.lang.reflect.Method.invokeNative(Native Method)
 02-06 10:15:13.967 I/dalvikvm( 2040):   at java.lang.reflect.Method.invoke(Method.java:525)
 02-06 10:15:13.967 I/dalvikvm( 2040):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1187)
 02-06 10:15:13.967 I/dalvikvm( 2040):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
 02-06 10:15:13.967 I/dalvikvm( 2040):   at dalvik.system.NativeStart.main(Native Method)
下面是我所有的自定义代码

我有自己的客户演示者

public class CustomPresenter : MvxAndroidViewPresenter, ICustomPresenter
{
    // map between view-model and fragment host which creates and shows the view based on the view-model type
    private Dictionary<Type, IFragmentHost> dictionary = new Dictionary<Type, IFragmentHost>();

    public override void Show(MvxViewModelRequest request)
    {
        IFragmentHost host;
        if (this.dictionary.TryGetValue(request.ViewModelType, out host))
        {
            if (host.Show(request))
            {
                return;
            }
        }
        base.Show(request);
    }

    public void Register(Type viewModelType, IFragmentHost host)
    {
        this.dictionary[viewModelType] = host;
    }
}
公共类CustomPresenter:MvxAndroidViewPresenter、ICustomPresenter
{
//视图模型和片段主体之间的映射,片段主体根据视图模型类型创建并显示视图
私有字典=新字典();
公共覆盖无效显示(MvxViewModelRequest请求)
{
IFragmentHost宿主;
if(this.dictionary.TryGetValue(request.ViewModelType,out host))
{
if(主机显示(请求))
{
返回;
}
}
显示(请求);
}
公共无效寄存器(viewModelType类型,IFragmentHost主机)
{
this.dictionary[viewModelType]=主机;
}
}
我使用一个MvxFragmentActivity作为我的主机视图,它将在顶部包含内容部分,在底部包含选项卡,这也实现了ifFragmentHost。包括选项卡在内的所有页面都将是片段

public class FirstView : MvxFragmentActivity, IFragmentHost
{

    ChildTwoView _childTwo;

    public bool Show(Cirrious.MvvmCross.ViewModels.MvxViewModelRequest request)
    {
        // create view model
        var loaderService = Mvx.Resolve<IMvxViewModelLoader>();
        var viewModel = loaderService.LoadViewModel(request, null /* saved state */);

        _childTwo = (ChildTwoView)SupportFragmentManager.FindFragmentById(Resource.Layout.childtwoview);

        var customPresenter = Mvx.Resolve<ICustomPresenter>();
        //customPresenter.Register(Type)

        // decide which fragment to create based on the view-model type

        var fm = this.SupportFragmentManager;
        var ft = fm.BeginTransaction();


        if (viewModel.GetType().Name == "ChildTwoViewModel")
        {
            var fragmentView = new ChildTwoView();
            ft.Replace(Resource.Id.childViewHost, fragmentView);
        }

        //var fragmentView = viewModel.GetType().Name;
        // load fragment into view


        ft.AddToBackStack(null);
        ft.Commit();
        return true;
    }

    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);
        SetContentView(Resource.Layout.FirstView);

        var childView = new ChildView()
        {
            ViewModel = new ChildViewModel()
        };

        var tabView = new TabView()
        {
            ViewModel = new TabViewModel()
        };
        var fm = this.SupportFragmentManager;
        var ft = fm.BeginTransaction();
        //ft.Add(childView, "child");

        ft.Replace(Resource.Id.childViewHost, childView, "child");


        ft.Replace(Resource.Id.tabViewHost, tabView, "tab");
        ft.Commit();
    }

}
公共类第一视图:MvxFragmentActivity,ifFragmentHost
{
ChildTwoView childTwo;
公共bool Show(cirrius.MvvmCross.ViewModels.MvxViewModelRequest请求)
{
//创建视图模型
var loaderService=Mvx.Resolve();
var viewModel=loaderService.LoadViewModel(请求,null/*保存状态*/);
_childTwo=(ChildTwoView)支持FragmentManager.FindFragmentById(Resource.Layout.ChildTwoView);
var customPresenter=Mvx.Resolve();
//customPresenter.Register(类型)
//根据视图模型类型确定要创建的片段
var fm=this.SupportFragmentManager;
var ft=fm.BeginTransaction();
if(viewModel.GetType().Name==“ChildTwoViewModel”)
{
var fragmentView=new ChildTwoView();
ft.Replace(Resource.Id.childViewHost,fragmentView);
}
//var fragmentView=viewModel.GetType().Name;
//将片段加载到视图中
ft.AddToBackStack(空);
ft.Commit();
返回true;
}
创建时受保护的覆盖无效(捆绑包)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.FirstView);
var childView=new childView()
{
ViewModel=新的子视图模型()
};
var tabView=new tabView()
{
ViewModel=新选项卡ViewModel()
};
var fm=this.SupportFragmentManager;
var ft=fm.BeginTransaction();
//ft.Add(儿童视图,“儿童”);
ft.Replace(Resource.Id.childViewHost,childView,“child”);
ft.Replace(Resource.Id.tabViewHost,tabView,“tab”);
ft.Commit();
}
}
我正在Setup.cs中设置这些

protected override IMvxAndroidViewPresenter CreateViewPresenter()
{
    var customPresenter = new CustomPresenter();
    Mvx.RegisterSingleton<ICustomPresenter>(customPresenter);
    return customPresenter;
}
受保护的覆盖IMvxAndroidViewPresenter CreateViewPresenter()
{
var customPresenter=新的customPresenter();
Mvx.RegisterSingleton(customPresenter);
返回customPresenter;
}
非常感谢您的帮助

编辑


我决定反对这种方法,并使用标准的Android TabHost来保持应用程序之间的一致性。

错误说明了一切。您很可能忘记将
活动
属性添加到您的
儿童视图
中,例如:

[Activity]
public class ChildTwoView : Activity { ... }

哦,等等,您的
ChildTwoView
不是
活动
,此时您不能在演示者中使用内置的
Show
方法。它不支持
片段

好的,如何用showviewmodel命令替换当前片段?你是说我不能用那个命令吗?当然可以。你只需要让你的演示者完成这项艰巨的工作。有没有关于我如何让演示者完成这项工作的建议?一个简单的方法是在完全更改上下文时使用
MvxFragmentActivity
。我想让每个视图都成为一个MvxFragmentActivity,它会加载选项卡MvxFragment。我能想到的唯一问题是如何处理后堆栈。当我单击其中一个选项卡项目时,它将导航到新页面,该页面也将加载选项卡。但当按下后退按钮时,它将转到上一个选项卡项,此时它应关闭应用程序。