web-dev-qa-db-ja.com

プログラムで(動的に)追加されたフラグメントのgetChildFragmentManager()

プログラムで(動的に)追加されたFragmentsの使用方法(または「使用可能」)getChildFragmentManager()

これが私の例です。

MainActivityが1つ、OuterFragが1つ、InnerFragが1つあります。 OuterFragによってMainActivityFragmentManagerに動的に追加します。また、InnerFragを動的にOuterFragに追加することも、FragmentManagerによって動的に行います。しかし、InnerFragを置き換えないで、OuterFragの子としてOuterFragを正確に追加し、MainActivityの新しい子にしたいと思います。

この階層を保持したい:MainActivity -> OuterFrag -> InnerFrag。したがって、MainActivityは常にOuterFragを呼び出すことができます。

しかし、この階層から変更しないでください:MainActivity -> OuterFragこの階層:MainActivity -> InnerFragMainActivityOuterFragを失います。

ここに私のサンプルコードがあります。

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を変更しています。これは、Before:ObjectおよびAfter:Objectが変更された2つのSystem Print Outステートメントによって確認できます。 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()を削除します。 MainActivity.Java)のステートメント。そして、それは正しい階層を維持しています:MainActivity -> OuterFrag -> InnerFrag。ただし、元のフラグメント(outer_frag.xml)の単語を削除することはできません。

結論として、私は常にOuterFragMainActivityを参照したいと思います。そして、OuterFragをプレースホルダーとして機能させて、さまざまなInnerFragsをロードします。要するに、プログラムで(動的に)追加されたときに、OuterFraggetChildFragmentManager()を呼び出したいのです。

29
midnite

結論として、私は常にMainActivityのOuterFragを参照したいと思います。そして、OuterFragが異なるInnerFragsをロードするためのプレースホルダーとして機能するようにします。要するに、プログラムで(動的に)追加された場合、OuterFragでgetChildFragmentManager()を呼び出したいと思います。

これが必要な場合は、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をメインアクティビティに追加するためのコードは引き続き有効です。

45
Luksprog