[英]Nested fragment in a ViewPager with tabs
我们要进行“类似facebook”的导航。
我们有3个选项卡,以及一个ViewPager,因此在这里,我们有3个categorizedViewModel(请参见下文)。 每个页面都是一个TabRootFragment
public partial class MainView : MvxActionBarActivity, ActionBar.ITabListener
public class MvxFragmentTabPagerAdapter<TFragment> : FragmentPagerAdapter where TFragment : Fragment
private ViewPager pager;
protected override void OnCreate(Bundle bundle)
{
...
this.SupportActionBar.NavigationMode = (int)ActionBarNavigationMode.Tabs;
...
this.fragmentTabPagerAdapter = new MvxFragmentTabPagerAdapter<TabRootFragment>(this.SupportFragmentManager);
foreach (var categorizedViewModel in this.MainViewModel.CategorizedViewModels)
{
this.AddPage(this.fragmentTabPagerAdapter, categorizedViewModel);
}
this.pager.Adapter = this.fragmentTabPagerAdapter;
this.pager.SetOnPageChangeListener(new ViewPageListenerForActionBar(this.SupportActionBar));
}
private void AddPage(MvxFragmentTabPagerAdapter<TabRootFragment> adapter, CategorizedViewModel categorizedViewModel)
{
Mvx.Trace("MainView => AddPage {0}", Enum.GetName(typeof(Category), categorizedViewModel.Category));
var nestedFragement = new TestView();
nestedFragement.ViewModel = categorizedViewModel;
var fragment = new TabRootFragment(nestedFragement);
adapter.AddFragment(fragment);
ActionBar.Tab tab = this.SupportActionBar.NewTab();
tab.SetIcon(CategoryHelper.GetDrawableId(categorizedViewModel.Category));
tab.SetTabListener(this);
this.SupportActionBar.AddTab(tab);
}
public void OnTabSelected(ActionBar.Tab tab, FragmentTransaction ft)
{
Mvx.Trace("MainView => OnTabSelected()");
this.pager.SetCurrentItem(this.SupportActionBar.SelectedNavigationIndex, false);
}
对于每个选项卡(viewPager的每个片段),我们都有一个具有框架布局的TabRootFragment:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<FrameLayout
android:id="@+id/ChildFragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
因此,我们要向此TabRootFragment添加一些TabChildFragments,以便具有3个单独的片段堆栈(“类似于facebook” :)
public class TabRootFragment : Fragment
{
/// <summary>
/// The root children
/// </summary>
public TabChildFragment rootChildren;
/// <summary>
/// Initializes a new instance of the <see cref="TabRootFragment"/> class.
/// </summary>
/// <param name="rootChildren">The root children.</param>
public TabRootFragment(TabChildFragment rootChildren)
{
this.rootChildren = rootChildren;
}
/// <summary>
/// Called when [create view].
/// </summary>
/// <param name="inflater">The inflater.</param>
/// <param name="container">The container.</param>
/// <param name="savedInstanceState">State of the saved instance.</param>
/// <returns>View.</returns>
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
Mvx.Trace("TabRootFragment => OnCreateView");
return inflater.Inflate(Resource.Layout.TabRootFragment, container, false);
}
/// <summary>
/// Called when [view created].
/// </summary>
/// <param name="view">The view.</param>
/// <param name="savedInstanceState">State of the saved instance.</param>
public override void OnViewCreated(View view, Bundle savedInstanceState)
{
Mvx.Trace(
"TabRootFragment => OnViewCreated {0}",
Enum.GetName(typeof(Category), this.rootChildren.ViewModel.Category));
base.OnViewCreated(view, savedInstanceState);
this.ChildFragmentManager.BeginTransaction()
.Add(Resource.Id.ChildFragment, this.rootChildren)
.Commit();
}
一切顺利,直到我们到达TabRootFragment的OnViewCreated为止 。 当我们执行片段管理器事务时,我们会收到一个很好的异常:
Java.Lang.IllegalStateException: Activity has been destroyed
TabRootFragment似乎未附加到Activity。 但是它是由OnTabSelected方法中的SetCurrentItem设置为寻呼机的。
我如何通过ViewPager检查此片段是否与活动良好连接?
唐恩是对的,这与此有关: https : //stackoverflow.com/a/15656428/5210 :)
除外,我的片段从未分离,并从TabRootFragment的OnAttach方法正确应用所需的修补程序。
奖励:这样做的Xamarin代码:
public class TabRootFragment : MvxFragment
{
public override void OnAttach(Activity activity)
{
Mvx.Trace("TabRootFragment => OnAttach");
base.OnAttach(activity);
this.InitChildFragmentManagerState();
}
/// <summary>
/// Initializes the state of the child fragment manager.
/// </summary>
private void InitChildFragmentManagerState()
{
var classRefProp = typeof(Fragment).GetProperty(
"class_ref",
BindingFlags.NonPublic | BindingFlags.Static);
IntPtr classRef = (IntPtr)classRefProp.GetValue(this);
var field = JNIEnv.GetFieldID(
classRef,
"mChildFragmentManager",
"Landroid/support/v4/app/FragmentManagerImpl;");
JNIEnv.SetField(this.Handle, field, IntPtr.Zero);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.