问题描述
我正在尝试使用MvvmCross 6.1.2使用TabLayout和Fragments做一个非常简单的概念证明.为此,我实现了一个带有TabLayout和ViewPager的活动,该活动应该具有两个选项卡-每个选项卡包含一个只有一个TextView的不同片段.
I'm trying to make a very simple Proof of Concept with TabLayout and Fragments using MvvmCross 6.1.2. For this, I implemented an activity with a TabLayout and a ViewPager, which should have two tabs - each one containing a different fragment with just one TextView.
但是在显示此活动时,我收到了一个异常,然后在运行时崩溃:
But I'm receiving an exception followed by a crash on runtime, when this activity should be displayed:
代码
这是我的代码的样子,它是按照 Playground示例实现的和文档:
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);
}
}
FragmentTab1ViewModel.cs (和FragmentTab2ViewModel.cs同样)
FragmentTab1ViewModel.cs (and FragmentTab2ViewModel.cs likewise)
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 (和FragmentTab2ViewController.cs同样)
FragmentTab1ViewController.cs (and FragmentTab2ViewController.cs likewise)
[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只是带有TextView的LinearLayouts)
(FragmentTab1View.axml and FragmentTab2View.axml are just LinearLayouts with a TextView)
- 引发异常的原因是什么?
- 这是使用片段实现TabLayout的推荐方法吗?
- 遵循MvvmCross 6.x的良好做法可以解决此问题?
推荐答案
抛出该异常是因为该属性未在Presenter
的AttributeTypesToActionsDictionary
中注册.
That exception is thrown because that attribute is not registered in the AttributeTypesToActionsDictionary
of the Presenter
.
在代码中,您可以在方法 RegisterAttributeTypes 已注册,但要考虑到它在MvxAppCompatViewPresenter
中.此外,在文档指出该属性仅适用于AppCompat
.
In the code you can see that in the method RegisterAttributeTypes it's registered but take into account that it is in the MvxAppCompatViewPresenter
. Furthermore in the docs it states that that attribute only works on AppCompat
.
鉴于您收到该异常,我可以假定正在使用非AppCompat演示者,因此您正在使用MvxAndroidSetup
.
Given that you are getting that exception I can assume that the non-AppCompat presenter is being used, therefore you are using MvxAndroidSetup
.
要解决此问题,请确保使用的是AppCompat
类,尤其是如果您具有在何处设置 MvxAppCompatViewPresenter
.此外,请确保使用的是MvxAppCompatApplication
,如果强制使用Setup
的AppCompat
版本.
To solve this make sure you are using AppCompat
classes, in particular inherit from MvxAppCompatSetup
if you have a custom Setup that is where the MvxAppCompatViewPresenter
is set. Also make sure you are using MvxAppCompatApplication
so if forces you to use the AppCompat
version of the Setup
.
更新有关对异常MvvmCross.Exceptions.MvxException: ViewPager not found
我认为问题在于您正在导航到Initialize
中的子级视图模型,而不是在创建选项卡视图之后执行此操作,因此当您尝试导航至子级视图时,ViewPager可能尚未初始化,因此找不到.
I think that the problem is that you are navigating to the children viewmodels in the Initialize
instead of doing this after the tabs view is created so the ViewPager may not be initialized yet when you try to navigate to the children, therefore it is not found.
如游乐场Viewmodel ,您应该有一个命令,该命令调用一种方法来对ViewModel进行导航:
So as in the Playground Viewmodel you should have a command that calls a method to do the navigation on your 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);
}
并与游乐场视图,则应在TabLayoutViewController
中调用该命令:
And as in the Playground View you should call the command in your 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();
}
}
HIH
这篇关于如何在MvvmCross 6.x中正确使用TabLayout中的片段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!