好的,我终于搞清楚了:
如上所建议,首先我将片段创建更改为以编程方式完成,并将它们添加到子片段管理器中,就像这样:
public override View OnCreateView(LayoutInflater inflater, ViewGroup viewGroup, Bundle savedInstance)
{
var view = inflater.Inflate(Resource.Layout.MyView, viewGroup, false);
var tx = ChildFragmentManager.BeginTransaction();
tx.Add(Resource.Id.lhs_fragment_frame, new LhsFragment());
tx.Add(Resource.Id.rhs_fragment_frame, new RhsFragment());
tx.Commit();
return view;
}
如预期,每次我切换选项卡时,都会创建一个额外的Lhs/RhsFragment实例,但我注意到旧的Lhs/RhsFragment的OnCreateView也会被调用。因此,在每次切换选项卡后,会再次调用一次OnCreateView。切换10次选项卡=11次调用OnCreateView。这显然是错误的。
查看FragmentTabHost的源代码,我可以看到它在切换选项卡时只是分离并重新连接选项卡的内容片段。似乎父Fragment的ChildFragmentManager将子片段保留下来,并在重新连接父片段时自动重新创建它们的视图。
因此,我将片段的创建移至OnCreate中,仅当我们不从保存的状态加载时才这样做。
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
if (savedInstanceState == null)
{
var tx = ChildFragmentManager.BeginTransaction();
tx.Add(Resource.Id.lhs_fragment_frame, new LhsFragment());
tx.Add(Resource.Id.rhs_fragment_frame, new RhsFragment());
tx.Commit();
}
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup viewGroup, Bundle savedInstance)
{
return inflater.Inflate(Resource.Layout.MyView, viewGroup, false);
}
这个修复了创建额外视图和切换选项卡的问题,现在基本上可以工作了。
接下来的问题是保存和恢复视图状态。在子片段中,我需要保存并恢复当前选择的项目。最初我有类似于这样的代码(这是子片段的OnCreateView):
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance)
{
var view = inflater.Inflate(Resource.Layout.CentresList, container, false);
if (savedInstance != null)
{
_selection = savedInstance.GetString(KEY_SELECTION);
}
else
{
_selection =_items[0];
}
return view;
}
这样做的问题在于,选项卡主机在切换选项卡时不会调用OnSaveInstanceState。相反,子片段被保持活动状态,它的“_selection”变量可以被保留不变。
因此,我将管理选择的代码移至OnCreate中:
public override void OnCreate(Bundle savedInstance)
{
base.OnCreate(savedInstance);
if (savedInstance != null)
{
_selection = savedInstance.GetString(BK_SELECTION);
}
else
{
_selection = _items[0];
}
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance)
{
return inflater.Inflate(Resource.Layout.CentresList, container, false);
}
现在一切似乎都完美地运作,无论是在切换选项卡还是改变方向时。