複数のStackOverflowページを通過した後でも、attachToRootの意味を明確に理解できなかったため、この回答を書きました。以下は、LayoutInflaterクラスのinflate()メソッドです。
View inflate (int resource, ViewGroup root, boolean attachToRoot)
activity_main.xmlファイル、button.xmlレイアウト、および作成したMainActivity.javaファイルを見てください。
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
button.xml
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LayoutInflater inflater = getLayoutInflater();
LinearLayout root = (LinearLayout) findViewById(R.id.root);
View view = inflater.inflate(R.layout.button, root, false);
}
コードを実行すると、レイアウトにボタンは表示されません。これは、attachToRootがfalseに設定されているため、ボタンレイアウトがメインアクティビティレイアウトに追加されないためです。
LinearLayoutには、ビューをLinearLayoutに追加するために使用できるaddView(View view)メソッドがあります。これにより、ボタンレイアウトがメインアクティビティレイアウトに追加され、コードの実行時にボタンが表示されるようになります。
root.addView(view);
前の行を削除して、attachToRootをtrueに設定するとどうなるか見てみましょう。
View view = inflater.inflate(R.layout.button, root, true);
ここでも、ボタンのレイアウトが表示されています。これは、attachToRootが、指定された親に膨張レイアウトを直接アタッチするためです。この場合はルートのLinearLayoutです。ここでは、前のaddView(View view)メソッドの場合のように手動でビューを追加する必要はありません。
FragmentのattachToRootをtrueに設定すると、なぜIllegalStateExceptionが発生するのですか?
これは、フラグメントの場合、フラグメントレイアウトをアクティビティファイルのどこに配置するかをすでに指定しているためです。
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.add(R.id.root, fragment)
.commit();
アドオン(int型の親、断片の断片)は、親のレイアウトにそれのレイアウトを持つフラグメントを追加します。attachToRootをtrueに設定すると、IllegalStateException:指定された子にはすでに親があります。フラグメントレイアウトは既にadd()メソッドで親レイアウトに追加されているため。
Fragmentsを膨らませているときは、attachToRootに常にfalseを渡す必要があります。Fragmentを追加、削除、置換するのはFragmentManagerの仕事です。
私の例に戻ります。両方を実行するとどうなるでしょうか。
View view = inflater.inflate(R.layout.button, root, true);
root.addView(view);
1行目で、LayoutInflaterはボタンレイアウトをルートレイアウトにアタッチし、同じボタンレイアウトを保持するViewオブジェクトを返します。2行目では、同じViewオブジェクトを親ルートレイアウトに追加しています。これにより、Fragmentsで見たのと同じIllegalStateExceptionが発生します(指定した子には既に親があります)。
デフォルトでattachToRootをtrueに設定する別のオーバーロードされたinflate()メソッドがあることに注意してください。
View inflate (int resource, ViewGroup root)