getChildFragmentManager()以编程方式(动态)添加片段?

时间:2012-12-07 06:11:42

标签: android android-fragments android-nested-fragment

如何使用(或"我们可以使用")getChildFragmentManager()以编程方式(动态)添加Fragment吗?

以下是我的例子。

我有一个MainActivity,一个OuterFrag和一个InnerFrag。我会OuterFrag动态地将MainActivity添加到FragmentManager。此外,我还会InnerFrag动态地将OuterFrag添加到FragmentManager。但我想将InnerFrag完全添加为OuterFrag的子项,而不是替换OuterFrag并成为MainActivity的新子项。

我想保留此层次结构:MainActivity -> OuterFrag -> InnerFrag。因此,MainActivity总是可以调用OuterFrag。

但不要从此层次结构更改MainActivity -> OuterFrag到此层次结构:MainActivity -> InnerFrag MainActivity将丢失OuterFrag

以下是我的示例代码。

MainActivity.java

package com.example.frag;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;

public class MainActivity extends FragmentActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        getSupportFragmentManager().beginTransaction().add(R.id.frameLayout, new OuterFrag()).commit();
        getSupportFragmentManager().executePendingTransactions();

        System.out.println("Before: "
                + getSupportFragmentManager().findFragmentById(R.id.frameLayout));

        ((OuterFrag) getSupportFragmentManager().findFragmentById(R.id.frameLayout))
                .addInnerFrag();

        System.out.println("After: "
                + getSupportFragmentManager().findFragmentById(R.id.frameLayout));
    }
}

activity_main.xml中

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/frameLayout"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
</FrameLayout>

OuterFrag.java

package com.example.frag;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class OuterFrag extends Fragment {
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.outer_frag, container, false);
    }

    public void addInnerFrag() {

        getFragmentManager().beginTransaction().replace(this.getId(), new InnerFrag()).commit();
        getFragmentManager().executePendingTransactions();

//        getChildFragmentManager().beginTransaction().add(this.getId(), new InnerFrag()).commit();
//        getChildFragmentManager().executePendingTransactions();
    }
}

outer_frag.xml

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/textView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="i am the OUTER frag" />

InnerFrag.java

package com.example.frag;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class InnerFrag extends Fragment {
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.inner_frag, container, false);
    }
}

inner_frag.xml

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/textView2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="i am the INNER frag" />

目前,上面的代码可以正常运行。但它实际上正在将InnerFrag更改为MainActivity的新子项。这可以通过两个System Print Out语句验证:Before:Object和After:Object被更改。在OuterFrag.java中,如果运行getChildFragmentManager()语句而不是getFragmentManager()语句,我们将收到以下运行时错误:

12-07 02:29:38.406: E/AndroidRuntime(12051): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.frag/com.example.frag.MainActivity}: java.lang.IllegalArgumentException: No view found for id 0x7f070000 (com.example.frag:id/frameLayout) for fragment InnerFrag{46e32748 #0 id=0x7f070000}

使用getChildFragmentManager()在理论上是正确的。它可以在非程序化添加的片段中使用(这意味着将activity_main.xml <FrameLayout>更改为<fragment>,添加属性android:name="com.example.frag.OuterFrag",然后删除第一个getSupportFragmentManager() {1}}中的{1}}语句。它保持了正确的层次结构:MainActivity.java。但是原始片段(MainActivity -> OuterFrag -> InnerFrag)的单词永远不能被删除。

总之,我想始终在outer_frag.xml中引用OuterFrag。我希望MainActivity充当占位符来加载不同的OuterFrag。简而言之,我想在InnerFrag中调用getChildFragmentManager(),当它以编程方式(动态)添加时。

2 个答案:

答案 0 :(得分:45)

  

总之,我想总是在MainActivity中引用OuterFrag。   我希望OuterFrag充当占位符来加载不同的东西   InnerFrags。简而言之,我想调用getChildFragmentManager()   OuterFrag,以编程方式(动态)添加。

如果你想要这个,那么让你的OuterFrag有一个容器布局作为其内容,并将InnerFrag添加到该容器中。 OuterFrag的布局文件为:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fragContainer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
/>

当然,如果您愿意,可以在OuterFrag的布局中添加其他视图。然后您的addInnerFrag方法将是:

public void addInnerFrag() {
        getChildFragmentManager().beginTransaction().add(R.id.fragContainer, new InnerFrag()).commit();
        getChildFragmentManager().executePendingTransactions();
}

OuterFrag添加到主要活动的代码仍然有效。

答案 1 :(得分:-1)

如果您想在addInnerFrag()代码中致电OuterFrag.java,可以这样做:

<强> OuterFrag.java:

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    addInnerFrag();
}