【问题标题】:Nested fragment in a ViewPager with tabs带有标签的 ViewPager 中的嵌套片段
【发布时间】:2014-10-15 22:07:35
【问题描述】:

我们想做一个“类似facebook”的导航。

我们有 3 个标签,带有一个 ViewPager,所以这里我们有 3 个分类视图模型(见下文)。 每个页面都是一个 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 中添加一些 TabChildFragment,以便拥有 3 个独立的片段堆栈(“facebook-like”:)

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 检查此片段是否很好地附加到活动?

【问题讨论】:

  • 这是一个非常相似的问题,你检查了吗? stackoverflow.com/a/15656428/5210
  • 不,那不行。片段永远不会处于分离状态(永远不会调用 OnDetach)。
  • 好吧,如果你复制OnAttach中的代码,请看下面:)

标签: android xamarin android-viewpager android-tabs android-nested-fragment


【解决方案1】:

Donn 是对的,这与此有关: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);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-17
    • 2013-09-14
    • 1970-01-01
    • 2013-11-17
    • 2014-01-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多