この回答を書いたのは、いくつかの 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>
ボタン.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) メソッドを使用して行ったように、手動でビューを追加する必要はありません。
フラグメントに対して attachToRoot を true に設定すると、IllegalStateException が発生するのはなぜですか。
これは、フラグメントのレイアウトをアクティビティ ファイル内のどこに配置するかを既に指定しているためです。
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.add(R.id.root, fragment)
.commit();
add(int parent, Fragment fragment)は、レイアウトを持つフラグメントを親レイアウトに追加します。attachToRoot を true に設定すると、IllegalStateException: The specified child already has a parent が発生します。フラグメント レイアウトは、add() メソッドで親レイアウトに既に追加されているためです。
Fragments をインフレートするときは、常に attachToRoot に false を渡す必要があります。フラグメントを追加、削除、置換するのは FragmentManager の仕事です。
私の例に戻ります。両方やったらどうでしょう。
View view = inflater.inflate(R.layout.button, root, true);
root.addView(view);
最初の行で、LayoutInflater はボタン レイアウトをルート レイアウトにアタッチし、同じボタン レイアウトを保持する View オブジェクトを返します。2 行目では、同じ View オブジェクトを親ルート レイアウトに追加します。これにより、フラグメントで見たのと同じ IllegalStateException が発生します (指定された子には既に親があります)。
デフォルトで attachToRoot を true に設定する別のオーバーロードされた inflate() メソッドがあることに注意してください。
View inflate (int resource, ViewGroup root)