251

ドキュメントは、パラメーターのLayoutInflater.inflate目的について正確に明確ではありません。attachToRoot

attachToRoot : 膨張した階層をルート パラメーターにアタッチする必要があるかどうか。false の場合、ルートは XML のルート ビューの LayoutParams の正しいサブクラスを作成するためにのみ使用されます。

具体的には、ルート ビューとは何かを詳しく説明し、truefalse値の間の動作の変化の例を示してください。

4

12 に答える 12

99

true に設定すると、レイアウトが膨張したときに、2 番目のパラメーターで子として指定された ViewGroup のビュー階層に自動的に追加されます。たとえば、ルート パラメータが のLinearLayout場合、膨張したビューはそのビューの子として自動的に追加されます。

false に設定されている場合、レイアウトは拡張されますが、他のレイアウトにはアタッチされません (したがって、描画されず、タッチ イベントなどを受け取りません)。

于 2012-09-24T14:58:55.200 に答える
27

ドキュメントと前の2つの回答で十分なはずです。私からの考えだけです。

このinflateメソッドは、レイアウト ファイルを膨張させるために使用されます。これらの膨張したレイアウトでは、それらを親に直接アタッチするViewGroupか、そのレイアウト ファイルからビュー階層を膨張させて、通常のビュー階層の外で操作する必要があります。

最初のケースでは、attachToRootパラメーターを に設定する必要があります(または、レイアウト ファイルと親ルート(非) を受け取るメソッドをtrue使用するのは非常に簡単です)。この場合、返される は単にメソッドで渡された であり、インフレートされたビュー階層が追加されます。inflateViewGroupnullViewViewGroupViewGroup

2 番目のオプションでは、レイアウト ファイルViewのルートが返されます。ペアの質問ViewGroupからの最後の議論を覚えているなら、これがの制限の理由の 1 つです(ルートとしてのレイアウト ファイルが膨張する場合、親を指定し、に設定する必要があります)。ルート aタグを含むレイアウト ファイルがあり、それに設定されていた場合、メソッドには同等のものがないため、何も返されません。また、ドキュメントにあるように、正しいバージョンでビュー階層を作成できるため、に設定されたバージョンが重要ですinclude-mergemergemergeattachedToRoottruemergeattachedToRootfalseinflatemergeinflateattachToRootfalseLayoutParams親から。これは場合によっては重要であり、メソッド セットがサポートされていないAdapterViewのサブクラスであるの子で最も顕著です。メソッドで次の行を使用したことを覚えていると思います。ViewGroupaddView()getView()

convertView = inflater.inflate(R.layout.row_layout, parent, false);

この行により、インフレートされたファイルのルートに設定されたサブクラスからR.layout.row_layoutの正しいものが確実に含まれるようになります。これを行わないと、ルートが. また、いくつかの特別で重要なものがあり、それらのビューに正しい.LayoutParamsAdapterViewViewGroupRelativeLayoutTableLayout/TableRowLayoutParamsLayoutParams

于 2012-09-24T15:47:41.600 に答える
21

この回答を書いたのは、いくつかの 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)
于 2017-10-10T17:52:27.393 に答える
4

attachToRoottrue に設定するinflatedViewと、 が親ビューの階層に追加されます。したがって、ユーザーがタッチ イベント (またはその他の UI 操作) を「見て」感知する可能性があります。それ以外の場合は、作成されたばかりで、どのビュー階層にも追加されていないため、タッチ イベントを表示したり処理したりできません。

Android を初めて使用する iOS 開発者attachToRootの場合、true に設定すると、次のメソッドが呼び出されます。

[parent addSubview:inflatedView];

さらに進むと、次のように尋ねるかもしれません: に設定attachToRootした場合、親ビューを渡す必要があるのはなぜfalseですか? これは、XML ツリーのルート要素が親ビューでいくつかの LayoutParams を計算する必要があるためです (親の一致など)。

于 2015-12-21T05:59:05.863 に答える
0

親を定義すると、 attachToRoot は、インフレータが実際に親にアタッチするかどうかを決定します。場合によっては、これにより問題が発生します。ListAdapter のように、リストがビューをリストに追加しようとして例外が発生しますが、既にアタッチされていると表示されます。ビューを自分で膨張させてアクティビティに追加するだけの場合は、便利でコード行を節約できます。

于 2012-09-24T14:58:42.970 に答える