【问题标题】:Android ActionBar.Tab, Fragments, Sub-fragmentsAndroid ActionBar.Tab、片段、子片段
【发布时间】:2014-02-26 16:17:50
【问题描述】:

我目前有一个 Android 应用程序,它在导航区域中有几个选项卡(确切地说是 3 个)。单击每个选项卡会显示与该选项卡关联的片段。

我希望能够单击正在显示的片段中的按钮并显示一个新片段,该片段不属于任何选项卡。基本上,它就像上一页的子屏幕。

我能够显示“子片段”,单击后退按钮将带我到上一个片段,这正是我想要的。

我的问题是,当我单击另一个选项卡时,“子片段”并没有消失。如果我点击后退按钮,我会得到一个 IllegalStateException,说 Fragment1 已经被添加。

这里有一些代码,希望能帮助回答我的问题。

主活动:

public void OnTabSelected(ActionBar.Tab tab, FragmentTransaction ft)
    {
        string tabTag = tab.Tag.ToString();

        Fragment f = FragmentManager.FindFragmentByTag(tabTag);

        if (f != null)
        {
            ft.Show(f);
        }
        else
        {
            switch (tabTag)
            {
                case "Tab1":
                    f = new Fragment1();
                    break;
                case "Tab2":
                    f = new Fragment2();
                    break;
                case "Tab3":
                    f = new Fragment3();
                    break;
                default:
                    f = new NotImplementedTabFragment();
                    break;
            }

            ft.Add(Resource.Id.fragmentContainer, f, tabTag);
         }
    }

    public void OnTabUnselected(ActionBar.Tab tab, FragmentTransaction ft)
    {
        string tabTag = tab.Tag.ToString();

        Fragment f = FragmentManager.FindFragmentByTag(tabTag);

        if (f != null)
        {
            ft.Hide(f);
        }
    }

片段1:

public class Fragment1 : Fragment
{

    public override Android.Views.View OnCreateView(Android.Views.LayoutInflater inflater, Android.Views.ViewGroup container, Bundle savedInstanceState)
    {
        base.OnCreateView(inflater, container, savedInstanceState);

        var view = inflater.Inflate(Resource.Layout.Fragment1, container, false);
        return view;
    }

    protected void OnButtonClick(object sender, Android.Widget.AdapterView.ItemClickEventArgs e)
    {
        var t = items[e.Position].ToString();
        FragmentTransaction fragmentTransaction = FragmentManager.BeginTransaction();
        fragmentTransaction.Replace(Resource.Id.fragmentContainer, new SubFragment());
        fragmentTransaction.AddToBackStack(null);
        fragmentTransaction.Commit();
    }
}

这是用 Xamarin (C#) 编写的,但我确实了解 Java 代码,因此任何使用 Java 的帮助/示例都可以。

更新:

我意识到我的 MainActivityLayout.axml 文件使用的是 RelativeLayout 而不是 FrameLayout 这就是为什么我必须使用附加/分离而不是显示/隐藏。这是我的新布局:

<?xml version="1.0" encoding="utf-8"?>
<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/fragmentContainer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1" />
</LinearLayout>

它仍然没有按预期工作,但我不再收到异常说片段已添加。

更新 2:

我决定放弃尝试使用 OnTabSelected 和 OnTabUnselected,而只使用委托,因为我使用的是 C#。重要的代码是这样的:

private void AddTab(Tab tab, Fragment fragment)
{
    Android.App.ActionBar.Tab droidTab = this.ActionBar.NewTab();
    droidTab.SetCustomView(new TabLayout(this));
    droidTab.SetTag(tab.ToString());

    droidTab.TabSelected += delegate(object sender, ActionBar.TabEventArgs e)
    {
        e.FragmentTransaction.Replace(Resource.Id.fragmentContainer, fragment);
    };

    this.ActionBar.AddTab(droidTab);
}

【问题讨论】:

    标签: android android-fragments tabs


    【解决方案1】:

    我认为您需要做的是保存对 SubFragment 的引用

    Fragment subFrag;
    protected void OnButtonClick(object sender, Android.Widget.AdapterView.ItemClickEventArgs e)
    {
        var t = items[e.Position].ToString();
        FragmentTransaction fragmentTransaction = FragmentManager.BeginTransaction();
        subFrag =  new SubFragment();
        fragmentTransaction.Replace(Resource.Id.fragmentContainer, subFrag);
        fragmentTransaction.AddToBackStack(null);
        fragmentTransaction.Commit();
    }
    

    然后当 Fragment1 被分离时,移除 subFrag

    @Override public void onDetach() {
        if (subFrag != null) {
             FragmentTransaction fragmentTransaction = FragmentManager.BeginTransaction();
             fragmentTransaction.Remove(subFrag );
             fragmentTransaction.Commit();
        }
        super.onDetach();
    }
    

    另一个(虽然我认为有点粗略)选项可能是在 Fragment1 中实现 getSubFragment() 方法并执行以下操作:

    public void OnTabUnselected(ActionBar.Tab tab, FragmentTransaction ft)
    {
        string tabTag = tab.Tag.ToString();
    
        Fragment f = FragmentManager.FindFragmentByTag(tabTag);
    
        if (f instanceof Fragment1) {
            Fragment subFrag = ((Fragment1)f).getSubFragment();
            if (subFrag != null) {
                ft.Remove(f); 
            }
        }
        if (f != null)
        {
            ft.Hide(f);
        }
    }
    

    【讨论】:

    • 我已经实现了你所说的,但永远不会调用 onDetach。根据 groups.google.com/forum/#!topic/android-platform/QlkLMsncDwg 的 Dianne Hackborn 的说法 - “不,这有点不幸命名。onDetach() 表示与活动分离。您的片段仍附加到活动。FragmentManager.detach() 基本上将其置于与何时相同的状态它被推送到片段返回堆栈上。”
    • 您是否尝试将其移至生命周期的另一部分,例如 onDestroyView 或 onPause?
    • 查看我的更新。我使用的是 RelativeLayout 而不是 FrameLayout 来存储片段。代码还没有按照我想要的方式工作。单击其他选项卡时,它不会使 SubFragment 消失,但会显示其他片段的内容。有点像分层效果。
    • 在java中你通常会使用getChildFragmentManager来获取一个FragmentManager来管理子片段,只是一个想法。稍后将发布另一个建议。
    猜你喜欢
    • 1970-01-01
    • 2019-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多