【问题标题】:Replacement of TabActivity with FragmentActivity and Fragments用 FragmentActivity 和 Fragments 替换 TabActivity
【发布时间】:2012-09-10 08:30:49
【问题描述】:

由于不推荐使用 TabActivity,我需要找到一种使用 Fragments 的方法。在我知道它是如何工作之前,我已经使用过 Fragments,但我需要一个指南来使用 FragmentActivities 创建我的标签主机。我在互联网上找到了几个例子,它们都是关于将片段放入选项卡的容器中。

我想要的是为每个标签放置 FragmentActivities。因为在我的应用程序中,我将使用 4 个选项卡,每个选项卡中都有非常复杂的内容。因此,我需要为每个选项卡设置一个 FragmentActivity 来管理我将放在单独容器中的每个选项卡下的 Fragment。

解决方案:

在互联网上回答和搜索后,我最终得到了一个解决方案。根据我找到的解决方案,我在标签主机下的每个标签的单独堆栈中跟踪片段。 Here 是我的 GitHub 存储库,我为这个问题创建了一个小示例应用程序。

【问题讨论】:

    标签: android android-fragments android-tabhost android-fragmentactivity


    【解决方案1】:

    由于不推荐使用 TabActivity,我需要找到一种使用 Fragments 的方法。

    如果您不想使用TabActivity - 忘记将FragmentActivities 放入标签的内容。

    我提醒您可以使用TabWidget 而不使用TabActivity。所以你可以试试这个解决方案:

    1. 只创建一个FragmentActivity
    2. TabWidget 放入FragmentActivity 的布局中。使TabWidget的内容高度=0。
    3. 在 XML 中的TabWidget 下为您声明容器Fragments(例如FrameLayout)。
    4. FragmentActivity 中,只需处理选择了哪个选项卡(TabHost.OnTabChangeListener)并将所需的Fragment 放入容器中。
    5. 将程序逻辑(之前在不同活动中)放入不同的片段中。

    或者您可以使用TabWidget 创建FragmentActivity,而不是切换Fragments,您可以直接将Fragments 放入每个选项卡的内容中。

    例如,如果您有 3 个选项卡和 3 个片段,请尝试我所做的。当您需要将一个片段更改为另一个片段时,请致电showFragmentX

    public class Test extends FragmentActivity {
    
    private Fragment1 fragment1=new Fragment1();
    private Fragment2 fragment2=new Fragment2();
    private Fragment3 fragment3=new Fragment3();
    
    private void showFragment1(){
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.replace(R.id.fragments_container, fragment1);
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        ft.commit();
    }
    
    private void showFragment2(){
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.replace(R.id.fragments_container, fragment2);
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        ft.commit();
    }
    
    private void showFragment3(){
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.replace(R.id.fragments_container, fragment3);
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        ft.commit();
    }
    
    @Override
    protected void onCreate(Bundle arg0) {
        // TODO Auto-generated method stub
        super.onCreate(arg0);
        setContentView(R.layout.fragmentactivity_layout);
    }
    }
    

    如果您这样做,您的fragmentX 变量不会在您每次将它们放入fragment_container 时被删除。他们会在你的FragmentActivity 活着的时候活着。看看fragments lifecycle。 只有OnCreateViewonDestroyView 片段的方法会在你replace 一个片段到另一个片段时一次又一次地调用。

    Fragments 还有他们的onSaveInstanceState 方法,您可以在其中保存片段的状态。例如:用户在 fragment1 的 editText 中输入了他的名字。如果您想在用户发现其他片段时保留此数据(名称字符串),您应该

    1.在fragment1的onSaveInstanceState方法中保存名称字符串
    2.进入fragment1的onCreateView方法检查savedInstanceState包,如果它不为null - 用你从包中获得的字符串填充edittext。

    public class Fragment1 extends Fragment {
    
    EditText nameEditText;
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,  Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
    
        View fragment1View=inflater.inflate(R.layout.fragment1_layout, container, false);
        nameEditText=(EditText) fragment1View.findViewById(R.id.edittext_name);
    
        //check for saved data. if it is not null - fill your edittext with saved string
        if(savedInstanceState!=null){
            String nameString=(String) savedInstanceState.get("nameString");
            nameEditText.setText(nameString);
        }
        return fragment1View;
    }
    
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        //save data that user have entered
        outState.putString("nameString", nameEditText.getText().toString());
    }
    

    }

    您可以在保存前检查数据。我希望我的观点现在很清楚了。

    此外,如果您在fragmentonCreateView() 方法中调用setRetainInstance(true) - 系统将尝试保存片段的状态(包含所有输入数据)。 link to description

    【讨论】:

    • 感谢答案,但是如果我将片段而不是活动放入选项卡中,则会出现另一个问题。例如,在第一个选项卡中,如果用户单击一个按钮,我想用另一个片段替换容器,然后如果我更改选项卡转到第二个选项卡,这将替换以前的片段。因此,如果我再次转到第一个选项卡,它将再次创建片段,我将无法看到上一页。你知道如何摆脱它吗?
    • 我已经编辑了我的答案。看看那个。样本中也有片段示例(“ApiDemos”)。检查出来。
    • 是的,我知道了,但这不是我要问的。我使用过片段,我知道它是如何工作的。我不知道的是:假设我们在第一个选项卡中,并且在用户单击按钮的情况下我调用了另一个片段,第二步我将选项卡更改为第二个,所以这里将替换数据在它与第二个标签的片段对吗?但我也想保留第一个选项卡中已更改的内容。所以以这种方式如果我只是替换片段 onTabChange 这将不会保留先前更改的内容在前一个选项卡中。有什么想法吗?
    • 好的,我好像明白你的问题了。我已经再次编辑了我的答案!看看:)
    • @QadirHussain 请参阅我的问题中的编辑。您可以找到包含我的解决方案的示例应用程序。希望有帮助。
    【解决方案2】:

    将选项卡内容放入单独的活动中的方法已被弃用,因为现在我们有了 Fragment 框架。您应该将选项卡的复杂内容放入片段中,并在用户选择选项卡时交换这些片段。

    为此推荐的解决方案是使用带有 Tab 导航的 ActionBar,而不是使用 TabHost 小部件。

    【讨论】:

    • 感谢您的回答,我对使用它有些顾虑。例如,如果我为第一个选项卡放置一个片段,我将需要在同一个选项卡中进行导航,据我所知,我们只为整个选项卡和其中的片段使用一个容器,所以在添加几个片段到第一个选项卡中的主容器,我将其更改为第二个选项卡,所以当我这样做时,这将删除我创建的所有片段并放入第一个选项卡中的容器中,并将第二个片段放入主容器,
    • 这意味着我在第一个选项卡中创建的所有数据都将被删除并替换为第二个片段?如果我回到第一个选项卡怎么办?我会重新创建它吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多