代码之家  ›  专栏  ›  技术社区  ›  Vinícius Queiroz Usman Kurd

如何使用MvvmCross 6.x在TabLayout中正确使用片段

  •  1
  • Vinícius Queiroz Usman Kurd  · 技术社区  · 7 年前

    问题

    但我收到一个异常,然后在运行时崩溃,此时应该显示此活动:

    演示者词典

    代码

    这就是我的代码的样子,我是按照 Playground example 以及 Documentation :

    AppStart.cs:

    public class AppStart : MvxAppStart
    {
        private readonly IMvxNavigationService _mvxNavigationService;
    
        public AppStart(IMvxApplication app, IMvxNavigationService mvxNavigationService)
            : base(app, mvxNavigationService)
        {
            _mvxNavigationService = mvxNavigationService;
        }
    
        protected override void NavigateToFirstViewModel(object hint = null)
        {
            Mvx.Resolve<IMvxNavigationService>().Navigate<TabLayoutViewModel>();
        }
    }
    

    TabLayoutViewModel.cs表格

    public class TabLayoutViewModel: MvxViewModel
    {
        public override async Task Initialize()
        {
            await base.Initialize();
    
            var tasks = new List<Task>();
            tasks.Add(Mvx.Resolve<IMvxNavigationService>().Navigate<FragmentTab1ViewModel>());
            tasks.Add(Mvx.Resolve<IMvxNavigationService>().Navigate<FragmentTab2ViewModel>());
            await Task.WhenAll(tasks);
        }
    }
    

    片段tab1viewmodel.cs (与FragmentTab2ViewModel.cs类似)

    public class FragmentTab1ViewModel : MvxViewModel
    {
        public override Task Initialize()
        {
            return base.Initialize();
        }
    }
    

    TabLayoutViewController.cs表格

    [MvxActivityPresentation]
    [Activity(Label = "", ScreenOrientation = ScreenOrientation.Portrait, LaunchMode = LaunchMode.SingleTask, Theme = "@style/LoginTheme")]
    public class TabLayoutViewController: MvxAppCompatActivity<TabLayoutViewModel>
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
    
            SetContentView(Resource.Layout.TabLayoutView);
    
            var set = this.CreateBindingSet<TabLayoutViewController, TabLayoutViewModel>();
    
            set.Apply();
        }
    }
    

    TabLayoutView.axml

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.design.widget.CoordinatorLayout 
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:alwaysDrawnWithCache="false"
        android:background="#f4f4f4"
        android:minWidth="25px"
        android:minHeight="25px">
      <android.support.design.widget.TabLayout
          android:id="@+id/tabsTeste"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:paddingLeft="16dp"
          app:tabGravity="center"
          app:tabMode="scrollable" />
      <android.support.v4.view.ViewPager
          android:id="@+id/viewpagerTeste"
          android:layout_width="match_parent"
          android:layout_height="match_parent" />
    </android.support.design.widget.CoordinatorLayout>
    

    FragmentTab1ViewController.cs

    [MvxTabLayoutPresentation(ActivityHostViewModelType = typeof(TabLayoutViewModel), ViewPagerResourceId = Resource.Id.viewpagerTest, TabLayoutResourceId = Resource.Id.tabsTest, Title = "Tab A")]
    [Register("smartSolution.coleta.droid.view.FragmentTab1ViewController")]
    public class FragmentTab1ViewController : MvxFragment<FragmentTab1ViewModel>
    {
        public override Android.Views.View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
        {
            base.OnCreateView(inflater, container, savedInstanceState);
    
            var view = this.BindingInflate(Resource.Layout.FragmentTab1View, null);
    
            inflater.Inflate(Resource.Layout.FragmentTab1View, container, true);
    
            var set = this.CreateBindingSet<FragmentTab1ViewController, FragmentTab1ViewModel>();
    
            set.Apply();
    
            return view;
        }
    }
    

    (FragmentTab1View.axml和FragmentTab2View.axml只是带有文本视图的线性布局)

    1. 引发异常的原因是什么?
    2. 这是实现带有片段的TabLayout的推荐方法吗?
    3. 遵循mvvmcross6.x良好实践,可以做些什么来解决这个问题?
    1 回复  |  直到 7 年前
        1
  •  2
  •   fmaccaroni    7 年前

    抛出该异常是因为该属性未在 AttributeTypesToActionsDictionary Presenter .

    在代码中,您可以在方法中看到这一点 RegisterAttributeTypes MvxAppCompatViewPresenter . 此外,在 docs AppCompat .

    假设您得到了这个异常,我可以假设正在使用非AppCompat演示者,因此您正在使用 MvxAndroidSetup

    要解决此问题,请确保使用 应用程序兼容性 类,特别是继承自 MvxAppCompatSetup where 这个 已设置。还要确保您正在使用 MvxAppCompatApplication 所以如果 forces 你可以用 的版本 Setup .


    更新 关于例外情况的评论 MvvmCross.Exceptions.MvxException: ViewPager not found

    我认为问题是您正在导航到 Initialize

    Playground Viewmodel 您应该有一个调用方法的命令来在ViewModel上执行导航:

    ...
    ShowInitialViewModelsCommand = new MvxAsyncCommand(ShowInitialViewModels);
    ...
    
    public IMvxAsyncCommand ShowInitialViewModelsCommand { get; private set; }
    
    ...
    
    private async Task ShowInitialViewModels()
    {
        var tasks = new List<Task>();
        tasks.Add(Mvx.Resolve<IMvxNavigationService>().Navigate<FragmentTab1ViewModel>());
        tasks.Add(Mvx.Resolve<IMvxNavigationService>().Navigate<FragmentTab2ViewModel>());
        await Task.WhenAll(tasks);
    }
    

    就像在 Playground View 你应该在你的电脑里调用命令 TabLayoutViewController :

    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);
    
        SetContentView(Resource.Layout.TabLayoutView);
    
        var set = this.CreateBindingSet<TabLayoutViewController, TabLayoutViewModel>();
    
        set.Apply();
    
        if (bundle == null)
        {
            ViewModel.ShowInitialViewModelsCommand.Execute();
        }
    }