Was bedeutet der Parameter LayoutInflater attachToRoot?

201

Die LayoutInflater.inflateDokumentation ist mir über den Zweck des attachToRootParameters nicht genau klar .

attachToRoot : Soll die aufgeblasene Hierarchie an den Root-Parameter angehängt werden? Wenn false, wird root nur verwendet, um die richtige Unterklasse von LayoutParams für die Root-Ansicht in XML zu erstellen.

Könnte jemand bitte detaillierter erklären, insbesondere was die Stammansicht ist, und vielleicht ein Beispiel für eine Änderung des Verhaltens zwischen trueund falseWerten zeigen?

Jeff Axelrod
quelle
1
Siehe auch
blahdiblah

Antworten:

157

JETZT ODER NICHT JETZT

Der Hauptunterschied zwischen dem "dritten" Parameter attachToRoot, der wahr oder falsch ist, ist dieser.

Wenn Sie attachToRoot setzen

true: Fügen Sie die untergeordnete Ansicht JETZT dem übergeordneten Element hinzu.
false: Fügen Sie die untergeordnete Ansicht dem übergeordneten Element NOT NOW hinzu .
Fügen Sie es später hinzu. `

Wann ist das später ?

Das ist später, wenn Sie für z parent.addView(childView)

Ein häufiges Missverständnis ist, dass die untergeordnete Ansicht nicht zum übergeordneten Element hinzugefügt wird, wenn der Parameter attachToRoot false ist. FALSCH
In beiden Fällen wird die untergeordnete Ansicht zur übergeordneten Ansicht hinzugefügt. Es ist nur eine Frage der Zeit .

inflater.inflate(child,parent,false);
parent.addView(child);   

ist äquivalent zu

inflater.inflate(child,parent,true);

A BIG NO-NO
Sie sollten attachToRoot niemals als true übergeben, wenn Sie nicht dafür verantwortlich sind, die untergeordnete Ansicht dem übergeordneten Element hinzuzufügen.
ZB beim Hinzufügen eines Fragments

public View onCreateView(LayoutInflater inflater,ViewGroup parent,Bundle bundle)
  {
        super.onCreateView(inflater,parent,bundle);
        View view = inflater.inflate(R.layout.image_fragment,parent,false);
        .....
        return view;
  }

Wenn Sie den dritten Parameter als true übergeben, erhalten Sie wegen dieses Typen die IllegalStateException.

getSupportFragmentManager()
      .beginTransaction()
      .add(parent, childFragment)
      .commit();

Da Sie das untergeordnete Fragment bereits versehentlich in onCreateView () hinzugefügt haben. Wenn Sie add aufrufen, erfahren Sie, dass die untergeordnete Ansicht bereits zur übergeordneten Ansicht hinzugefügt wurde .
Hier sind Sie nicht für das Hinzufügen von childView verantwortlich, FragmentManager ist dafür verantwortlich. In diesem Fall also immer falsch übergeben.

HINWEIS: Ich habe auch gelesen, dass parentView keine childView touchEvents erhält, wenn attachToRoot false ist. Aber ich habe es nicht getestet.

Rohit Singh
quelle
6
Sehr hilfreich, vor allem der Teil bezüglich der FragmentManager, danke!
CybeX
94

Wenn der Wert auf true gesetzt ist, wird Ihr Layout beim Aufblasen automatisch zur Ansichtshierarchie der ViewGroup hinzugefügt, die im 2. Parameter als untergeordnetes Element angegeben ist. Wenn der Root-Parameter beispielsweise a war, LinearLayoutwird Ihre aufgeblasene Ansicht automatisch als untergeordnetes Element dieser Ansicht hinzugefügt.

Wenn es auf false gesetzt ist, wird Ihr Layout aufgeblasen, aber nicht an ein anderes Layout angehängt (es wird also nicht gezeichnet, es werden Berührungsereignisse empfangen usw.).

Joseph Earl
quelle
17
Ich bin verwirrt. Ich war immer ein „Angegebene Kind bereits einen Elternteil Fehler hat“ , bis wir lesen diese Antwort , die mein gerichtet verwenden falsefür attachToRootdas während meines Fragments onCreateView. Dies löste das Problem und noch das Layout des Fragments ist sichtbar und aktiv, trotz Ihrer Antwort. Was ist los hier?
Jeff Axelrod
67
Weil ein Fragment automatisch das von onCreateView zurückgegebene Layout anfügt. Wenn Sie es also manuell in onCreateView anhängen, wird Ihre Ansicht an zwei übergeordnete Elemente angehängt (was zu dem von Ihnen erwähnten Fehler führt).
Joseph Earl
11
Ich bin hier ein bisschen verwirrt, @JosephEarl Sie sagten, wenn gesetzt, truewird die Ansicht an den 2. Parameter angehängt, der der ist container, aber dann sagen Sie, Fragment wird automatisch von angehängt onCreateView(), so dass nach meinem Verständnis der dritte Parameter nutzlos ist und gesetzt werden sollte falseimmer?
Unmultimedio
5
Sie geben die Ansicht in oncreateview zurück, diese wird dann automatisch angehängt. Wenn Sie "Anhängen" auf "Wahr" setzen, wird ein Fehler ausgegeben. Wenn Sie die Ansicht jedoch in einer eigenständigen Situation aufblasen, können Sie die Ansicht automatisch an den Container anhängen, indem Sie auf true setzen. Ich habe mich jedoch kaum wahr gemacht, da ich die Ansicht immer selbst hinzufüge.
frostymarvelous
7
@unmultimedio ist nur für die von zurückgegebene Root-Ansicht nutzlos onCreateView. Wenn Sie weitere Layouts in diese Stammansicht aufblasen oder in einem anderen Kontext (z. B. in einer Aktivität) aufblasen, ist dies hilfreich.
Joseph Earl
36

Scheint viel Text in den Antworten zu sein, aber kein Code. Deshalb habe ich beschlossen, diese alte Frage mit einem Codebeispiel in mehreren Antworten wiederzubeleben:

Wenn der Wert auf true gesetzt ist, wird Ihr Layout beim Aufblasen automatisch zur Ansichtshierarchie der ViewGroup hinzugefügt, die im 2. Parameter als untergeordnetes Element angegeben ist.

Was das im Code tatsächlich bedeutet (was die meisten Programmierer verstehen), ist:

public class MyCustomLayout extends LinearLayout {
    public MyCustomLayout(Context context) {
        super(context);
        // Inflate the view from the layout resource and pass it as child of mine (Notice I'm a LinearLayout class).

        LayoutInflater.from(context).inflate(R.layout.child_view, this, true);
    }
}

Beachten Sie, dass der vorherige Code das Layout R.layout.child_viewals untergeordnetes Element MyCustomLayoutaufgrund von attachToRootparam is hinzufügt trueund die Layoutparameter des übergeordneten Elements genau so zuweist, als ob ich es addViewprogrammgesteuert verwenden würde oder als ob ich dies in XML getan hätte:

<LinearLayout>
   <View.../>
   ...
</LinearLayout>

Der folgende Code erläutert das Szenario beim Übergeben attachRootals false:

LinearLayout linearLayout = new LinearLayout(context);
linearLayout.setLayoutParams(new LayoutParams(
    LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
linearLayout.setOrientation(LinearLayout.VERTICAL);
    // Create a stand-alone view
View myView = LayoutInflater.from(context)
    .inflate(R.layout.ownRootView, null, false);
linearLayout.addView(myView);

Im vorherigen Code haben Sie angegeben, dass Sie myViewein eigenes Stammobjekt sein möchten und es keinem übergeordneten Objekt zuordnen möchten. Später haben wir es als Teil der LinearLayoutAnsicht hinzugefügt, aber für einen Moment war es eine eigenständige Ansicht (kein übergeordnetes Objekt ).

Dasselbe passiert mit Fragmenten. Sie können sie einer bereits vorhandenen Gruppe hinzufügen und Teil dieser Gruppe sein oder einfach die Parameter übergeben:

inflater.inflate (R.layout.fragment, null, false);

Um anzugeben, dass es sich um eine eigene Wurzel handelt.

Martin Cazares
quelle
1
Von allen war dies am hilfreichsten.
Wahib Ul Haq
26

Die Dokumentation und die beiden vorherigen Antworten sollten ausreichen, nur ein paar Gedanken von mir.

Die inflateMethode wird zum Aufblasen von Layoutdateien verwendet. Bei diesen aufgeblasenen Layouts müssen Sie die Möglichkeit haben, sie direkt an ein übergeordnetes ViewGroupElement anzuhängen oder einfach die Ansichtshierarchie aus dieser Layoutdatei aufzublasen und außerhalb der normalen Ansichtshierarchie damit zu arbeiten.

Im ersten Fall muss der attachToRootParameter auf gesetzt werden true(oder viel einfacher die inflateMethode verwenden, die eine Layoutdatei und ein übergeordnetes Stammverzeichnis ViewGroup(nicht null) verwendet). In diesem Fall ist die ViewRückgabe einfach ViewGroupdiejenige, die in der Methode übergeben wurde, ViewGroupzu der die aufgeblasene Ansichtshierarchie hinzugefügt wird.

Bei der zweiten Option Viewist das zurückgegebene Stammverzeichnis ViewGroupaus der Layoutdatei. Wenn Sie sich an unsere letzte Diskussion aus der include-mergePaarfrage erinnern, ist dies einer der Gründe für die mergeEinschränkung von (wenn eine Layoutdatei mit mergeals root aufgeblasen wird, müssen Sie ein übergeordnetes Element angeben und attachedToRootmüssen auf eingestellt sein true). Wenn Sie eine Layoutdatei mit dem Root- mergeTag a hatten und attachedToRootauf gesetzt waren, kann falsedie inflateMethode nichts zurückgeben, da mergesie kein Äquivalent hat. Wie in der Dokumentation angegeben, ist auch die inflateVersion mit attachToRootset to falsewichtig, da Sie die Ansichtshierarchie mit der richtigen erstellen könnenLayoutParamsvom Elternteil. Dies ist in einigen Fällen wichtig, insbesondere bei Kindern AdapterVieweiner Unterklasse von ViewGroup, für die die festgelegten addView()Methoden nicht unterstützt werden. Ich bin sicher, Sie erinnern sich daran, diese Zeile in der getView()Methode verwendet zu haben:

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

Diese Linie stellt sicher , dass der aufgeblasene R.layout.row_layoutDatei die richtige ist LayoutParamsaus der AdapterViewUnterklasse Satz auf seiner Wurzel ViewGroup. Wenn Sie dies nicht tun würden, könnten Sie Probleme mit der Layoutdatei haben, wenn das Stammverzeichnis a wäre RelativeLayout. Die TableLayout/TableRowhaben auch einige spezielle und wichtige LayoutParamsund Sie sollten sicherstellen, dass die Ansichten in ihnen die richtigen haben LayoutParams.

Luksprog
quelle
18

Ich selbst war auch verwirrt über das, was war der eigentliche Zweck des attachToRootin inflateMethode. Nach einigem UI-Studium bekam ich endlich die Antwort:

Elternteil:

In diesem Fall handelt es sich um das Widget / Layout, das die Ansichtsobjekte umgibt, die Sie mit findViewById () aufblasen möchten.

attachToRoot:

Hängt die Ansichten an die übergeordnete Ansicht an (schließt sie in die übergeordnete Hierarchie ein), sodass jedes Berührungsereignis, das die Ansichten erhalten, auch an die übergeordnete Ansicht übertragen wird. Jetzt ist es Sache der Eltern, diese Ereignisse zu unterhalten oder zu ignorieren. Wenn sie auf false gesetzt sind, werden sie nicht als direkte untergeordnete Elemente des übergeordneten Elements hinzugefügt, und das übergeordnete Element empfängt keine Berührungsereignisse aus den Ansichten.

Hoffe das klärt die Verwirrung

Umer Farooq
quelle
Ihre
Neon
11

Ich habe diese Antwort geschrieben, weil ich selbst nach dem Durchblättern mehrerer StackOverflow-Seiten nicht klar verstehen konnte, was attachToRoot bedeutet. Unten finden Sie die inflate () -Methode in der LayoutInflater-Klasse.

View inflate (int resource, ViewGroup root, boolean attachToRoot)

Schauen Sie sich die Datei activity_main.xml , das Layout button.xml und die von mir erstellte Datei MainActivity.java an .

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);
}

Wenn wir den Code ausführen, wird die Schaltfläche im Layout nicht angezeigt. Dies liegt daran, dass unser Schaltflächenlayout nicht zum Hauptaktivitätslayout hinzugefügt wird, da attachToRoot auf false gesetzt ist.

LinearLayout verfügt über eine addView- Methode (Ansichtsansicht) , mit der Ansichten zu LinearLayout hinzugefügt werden können. Dadurch wird das Schaltflächenlayout zum Hauptaktivitätslayout hinzugefügt und die Schaltfläche wird sichtbar, wenn Sie den Code ausführen.

root.addView(view);

Entfernen wir die vorherige Zeile und sehen, was passiert, wenn wir attachToRoot auf true setzen.

View view = inflater.inflate(R.layout.button, root, true);

Wieder sehen wir, dass das Schaltflächenlayout sichtbar ist. Dies liegt daran, dass attachToRoot das aufgeblasene Layout direkt an das angegebene übergeordnete Layout anfügt. Was in diesem Fall root LinearLayout ist. Hier müssen wir die Ansichten nicht manuell hinzufügen, wie wir es im vorherigen Fall mit der Methode addView (Ansichtsansicht) getan haben.

Warum erhalten Benutzer IllegalStateException, wenn attachToRoot für ein Fragment als true festgelegt wird?

Dies liegt daran, dass Sie für ein Fragment bereits angegeben haben, wo Ihr Fragmentlayout in Ihrer Aktivitätsdatei abgelegt werden soll.

FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
    .add(R.id.root, fragment)
    .commit();

Das Add (int parent, Fragment fragment) fügt das Fragment mit dem Layout zum übergeordneten Layout hinzu. Wenn wir attachToRoot auf true setzen, erhalten Sie IllegalStateException: Das angegebene Kind hat bereits ein Elternteil. Da das Fragmentlayout bereits in der add () -Methode zum übergeordneten Layout hinzugefügt wurde.

Sie sollten für attachToRoot immer false übergeben, wenn Sie Fragmente aufblasen. Es ist Aufgabe des FragmentManagers, Fragmente hinzuzufügen, zu entfernen und zu ersetzen.

Zurück zu meinem Beispiel. Was ist, wenn wir beides tun?

View view = inflater.inflate(R.layout.button, root, true);
root.addView(view);

In der ersten Zeile hängt LayoutInflater das Schaltflächenlayout an das Stammlayout an und gibt ein View-Objekt zurück, das dasselbe Schaltflächenlayout enthält. In der zweiten Zeile fügen wir dem übergeordneten Stammlayout dasselbe View-Objekt hinzu. Dies führt zu derselben IllegalStateException, die wir bei Fragmenten gesehen haben (das angegebene Kind hat bereits ein Elternteil).

Beachten Sie, dass es eine andere überladene inflate () -Methode gibt, mit der attachToRoot standardmäßig auf true gesetzt wird.

View inflate (int resource, ViewGroup root)
capt.swag
quelle
Einfache und klare Erklärung, genau das, wonach ich gesucht habe!
FlyingAssistant
10

Aufgrund der Dokumentation zur inflate () -Methode gibt es zu diesem Thema viel Verwirrung.

Wenn attachToRoot auf true gesetzt ist, wird die im ersten Parameter angegebene Layoutdatei im Allgemeinen aufgeblasen und zu diesem Zeitpunkt an die im zweiten Parameter angegebene ViewGroup angehängt. Wenn attachToRoot false ist, wird die Layoutdatei aus dem ersten Parameter aufgeblasen und als Ansicht zurückgegeben, und jeder Ansichtsanhang erfolgt zu einem anderen Zeitpunkt.

Dies bedeutet wahrscheinlich nicht viel, es sei denn, Sie sehen viele Beispiele. Wenn Sie LayoutInflater.inflate () innerhalb der onCreateView-Methode eines Fragments aufrufen, möchten Sie false für attachToRoot übergeben, da die diesem Fragment zugeordnete Aktivität tatsächlich für das Hinzufügen der Ansicht dieses Fragments verantwortlich ist. Wenn Sie eine Ansicht zu einem späteren Zeitpunkt manuell aufblasen und einer anderen Ansicht hinzufügen, z. B. mit der Methode addView (), sollten Sie false für attachToRoot übergeben, da der Anhang zu einem späteren Zeitpunkt erstellt wird.

In einem Blog-Beitrag, den ich zu diesem Thema geschrieben habe, können Sie einige andere einzigartige Beispiele zu Dialogen und benutzerdefinierten Ansichten lesen.

https://www.bignerdranch.com/blog/understanding-androids-layoutinflater-inflate/

Seanjfarrell
quelle
4

attachToRootAuf true gesetzt bedeutet, dass das inflatedViewder Hierarchie der übergeordneten Ansicht hinzugefügt wird. Somit können Benutzer möglicherweise "gesehen" werden und Berührungsereignisse (oder andere UI-Operationen) erfassen. Andernfalls wurde es nur erstellt, keiner Ansichtshierarchie hinzugefügt und kann daher keine Berührungsereignisse sehen oder verarbeiten.

Für iOS-Entwickler, die Android noch nicht kennen, attachToRootbedeutet true, dass Sie diese Methode aufrufen:

[parent addSubview:inflatedView];

Wenn Sie weiter gehen, fragen Sie sich möglicherweise: Warum sollte ich die übergeordnete Ansicht übergeben, wenn ich auf eingestellt attachToRoothabe false? Dies liegt daran, dass das Stammelement in Ihrem XML-Baum die übergeordnete Ansicht benötigt, um einige LayoutParams zu berechnen (z. B. Match Parent).

Alston
quelle
0

Wenn Sie das übergeordnete Element definieren, bestimmt attachToRoot, ob der Inflater es tatsächlich an das übergeordnete Element anhängen soll oder nicht. In einigen Fällen verursacht dies Probleme, wie in einem ListAdapter, der eine Ausnahme verursacht, da die Liste versucht, die Ansicht zur Liste hinzuzufügen, aber angibt, dass sie bereits angehängt ist. In anderen Fällen, in denen Sie die Ansicht nur selbst aufblasen, um sie zu einer Aktivität hinzuzufügen, kann dies nützlich sein und Ihnen eine Codezeile ersparen.

CaseyB
quelle
1
gibt kein klares Bild, das eine gute Antwort liefern sollte.
Prakhar1001
0

Zum Beispiel haben wir ein ImageView, ein LinearLayoutund ein RelativeLayout. LinearLayout ist das untergeordnete Element von RelativeLayout. Die Ansichtshierarchie wird sein.

RelativeLayout
           ------->LinearLayout

und wir haben eine separate Layoutdatei für ImageView

image_view_layout.xml

An root anhängen:

//here container is the LinearLayout

    View v = Inflater.Inflate(R.layout.image_view_layout,container,true);
  1. Hier enthält v die Referenz des Container-Layouts, dh das LinearLayout. Wenn Sie die Parameter wie setImageResource(R.drawable.np);in ImageView festlegen möchten, müssen Sie sie anhand der Referenz des übergeordneten Layouts finden, d. H.view.findById()
  2. Übergeordnetes Element von v ist das FrameLayout.
  3. LayoutParams werden von FrameLayout sein.

Nicht an root anhängen:

//here container is the LinearLayout
    View v = Inflater.Inflate(R.layout.image_view_layout,container,false);
  1. Hier enthält v das Layout ohne Referenzcontainer, aber einen direkten Verweis auf die aufgeblasene ImageView, sodass Sie ihre Parameter wie view.setImageResource(R.drawable.np);ohne Referenzierung wie einstellen können findViewById. Der Container wird jedoch so angegeben, dass ImageView die LayoutParams des Containers erhält, sodass Sie sagen können, dass die Referenz des Containers nur für LayoutParams bestimmt ist.
  2. In bestimmten Fällen ist Parent also null.
  3. LayoutParams werden von LinearLayout sein.
Faisal Naseer
quelle
0

attachToRoot Auf true setzen:

Wenn attachToRoot auf true gesetzt ist, wird die im ersten Parameter angegebene Layoutdatei aufgeblasen und an die im zweiten Parameter angegebene ViewGroup angehängt.

Stellen Sie sich vor, wir haben eine Schaltfläche in einer XML-Layoutdatei angegeben, deren Layoutbreite und Layouthöhe auf match_parent festgelegt sind.

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

Wir möchten diese Schaltfläche nun programmgesteuert zu einem linearen Layout innerhalb eines Fragments oder einer Aktivität hinzufügen. Wenn unser LinearLayout bereits eine Mitgliedsvariable, mLinearLayout, ist, können wir die Schaltfläche einfach wie folgt hinzufügen:

inflater.inflate(R.layout.custom_button, mLinearLayout, true);

Wir haben angegeben, dass der Button aus seiner Layoutressourcendatei aufgeblasen werden soll. Anschließend teilen wir dem LayoutInflater mit, dass wir es an mLinearLayout anhängen möchten. Unsere Layoutparameter werden berücksichtigt, da wir wissen, dass der Button einem LinearLayout hinzugefügt wird. Der Layoutparametertyp der Schaltfläche sollte LinearLayout.LayoutParams sein.

attachToRoot Auf false setzen (nicht erforderlich, um false zu verwenden)

Wenn attachToRoot auf false gesetzt ist, wird die im ersten Parameter angegebene Layoutdatei aufgeblasen und nicht an die im zweiten Parameter angegebene ViewGroup angehängt. Diese aufgeblasene Ansicht erhält jedoch die LayoutParams des übergeordneten Elements , sodass diese Ansicht korrekt in das übergeordnete Element passt.


Lassen Sie uns einen Blick darauf werfen, wann Sie attachToRoot auf false setzen möchten. In diesem Szenario wird die im ersten Parameter von inflate () angegebene Ansicht zu diesem Zeitpunkt nicht an die ViewGroup im zweiten Parameter angehängt.

Erinnern Sie sich an unser Button-Beispiel von früher, in dem wir einen benutzerdefinierten Button aus einer Layoutdatei an mLinearLayout anhängen möchten. Wir können unseren Button weiterhin an mLinearLayout anhängen, indem wir false für attachToRoot übergeben - wir fügen ihn anschließend einfach manuell hinzu.

Button button = (Button) inflater.inflate(R.layout.custom_button,    mLinearLayout, false);
mLinearLayout.addView(button);

Diese beiden Codezeilen entsprechen dem, was wir zuvor in einer Codezeile geschrieben haben, als wir true für attachToRoot übergeben haben. Durch die Übergabe von false sagen wir, dass wir unsere Ansicht noch nicht an die Root-ViewGroup anhängen möchten. Wir sagen, dass es zu einem anderen Zeitpunkt passieren wird. In diesem Beispiel ist der andere Zeitpunkt einfach die addView () -Methode, die unmittelbar unterhalb der Inflation verwendet wird.

Das Beispiel "false attachToRoot" erfordert etwas mehr Arbeit, wenn wir die Ansicht manuell zu einer ViewGroup hinzufügen.

attachToRoot Auf false setzen (false ist erforderlich)

Wenn Sie die Ansicht eines Fragments in onCreateView () aufblasen und zurückgeben, müssen Sie false für attachToRoot übergeben. Wenn Sie true übergeben, erhalten Sie eine IllegalStateException, da das angegebene Kind bereits ein Elternteil hat. Sie sollten angegeben haben, wo die Ansicht Ihres Fragments wieder in Ihrer Aktivität platziert werden soll. Es ist Aufgabe des FragmentManagers, Fragmente hinzuzufügen, zu entfernen und zu ersetzen.

FragmentManager fragmentManager = getSupportFragmentManager();
Fragment fragment =  fragmentManager.findFragmentById(R.id.root_viewGroup);

if (fragment == null) {
fragment = new MainFragment();
fragmentManager.beginTransaction()
    .add(R.id.root_viewGroup, fragment)
    .commit();
}

Der root_viewGroup-Container, der Ihr Fragment in Ihrer Aktivität enthält, ist der ViewGroup-Parameter, den Sie in onCreateView () in Ihrem Fragment erhalten haben. Es ist auch die ViewGroup, die Sie an LayoutInflater.inflate () übergeben. Der FragmentManager übernimmt jedoch das Anhängen der Ansicht Ihres Fragments an diese ViewGroup. Sie möchten es nicht zweimal anhängen. Setzen Sie attachToRoot auf false.

public View onCreateView(LayoutInflater inflater, ViewGroup  parentViewGroup, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_layout,     parentViewGroup, false);

return view;
}

Warum erhalten wir die übergeordnete ViewGroup unseres Fragments überhaupt, wenn wir sie nicht in onCreateView () anhängen möchten? Warum fordert die inflate () -Methode eine Root-ViewGroup an?

Es stellt sich heraus, dass wir auch dann, wenn wir unsere neu aufgeblasene Ansicht nicht sofort zur übergeordneten ViewGroup hinzufügen, die LayoutParams der übergeordneten Ansicht verwenden sollten, damit die neue Ansicht ihre Größe und Position bestimmen kann, wenn sie schließlich angehängt wird.

Link: https://youtu.be/1Y0LlmTCOkM?t=409

Utshaw
quelle
0

Ich teile nur einige Punkte, die mir bei der Arbeit an diesem Thema begegnet sind.

Zusätzlich zu der akzeptierten Antwort möchte ich einige Punkte ansprechen, die hilfreich sein könnten.

Wenn ich attachToRoot als true verwendet habe, war die zurückgegebene Ansicht vom Typ ViewGroup, dh die Stammansicht ViewGroup des Elternteils, die als Parameter für die Inflate- Methode (layoutResource, ViewGroup, attachToRoot) übergeben wurde , nicht vom Typ des übergebenen Layouts, sondern von attachToRoot Als false erhalten wir den Funktionsrückgabetyp der Root- ViewGroup dieser layoutResource .

Lassen Sie mich anhand eines Beispiels erklären:

Wenn wir eine Linearlayout als Root - Layout und dann wollen wir hinzufügen Textview in ihm durch aufblasen Funktion.

Wenn Sie dann attachToRoot als echte Aufblasfunktion verwenden, wird eine Ansicht vom Typ LinearLayout zurückgegeben

während auf der Verwendung attachToRoot als falsch aufblasen Funktion gibt eine Ansicht vom Typ Textview

Hoffe, dieser Befund wäre hilfreich ...

HARIS UMAID
quelle