Warum ignoriert LayoutInflater die von mir angegebenen Layoutparameter layout_width und layout_height?

167

Ich hatte ernsthafte Probleme damit, LayoutInflater wie erwartet zum Laufen zu bringen, und andere Leute auch: Wie verwende ich Layoutinflator, um zur Laufzeit Ansichten hinzuzufügen? .

Warum ignoriert LayoutInflater die von mir angegebenen Layoutparameter? ZB warum werden die layout_widthund layout_heightWerte aus meinen Ressourcen XML nicht berücksichtigt?

andig
quelle
Richtig - tut das weh oder habe ich den falschen Ort ausgewählt? Ich dachte nur, ich würde meine Ergebnisse teilen. Muss zugeben, Tutorials werden nicht speziell von der FAQ-Seite erwähnt ..
andig
3
siehe letzter Absatz der ersten Frage in FAQ. poste es als Frage und poste dann das Tutorial als Antwort. Natürlich können Sie diese Frage bearbeiten, indem Sie das Tutorial ausschneiden und in die Antwort einfügen. Ich werde abstimmen, wenn Sie dies beheben.
Bigstones

Antworten:

380

Ich habe dieses Problem untersucht, mich auf die LayoutInflater-Dokumente bezogen und ein kleines Beispiel-Demonstrationsprojekt eingerichtet. Die folgenden Tutorials zeigen, wie Sie ein Layout mithilfe dynamisch füllen LayoutInflater.

Bevor wir anfangen, sehen Sie, wie LayoutInflater.inflate()Parameter aussehen:

  • Ressource : ID für eine zu ladende XML-Layoutressource (z. B. R.layout.main_page)
  • Wurzel : Optional Ansicht der Elternteil der erzeugten Hierarchie werden (wenn attachToRootist true) oder auch nur ein Objekt , das einen Satz liefert LayoutParamsWerte für die Wurzel der Hierarchie zurückgeführt (wenn attachToRootist false) .
  • attachToRoot : Soll die aufgeblasene Hierarchie an den Root-Parameter angehängt werden? Wenn false, wird root nur verwendet, um die richtige Unterklasse LayoutParamsfür die Root-Ansicht im XML zu erstellen .

  • Rückgabe : Die Stammansicht der aufgeblasenen Hierarchie. Wenn root angegeben wurde und attachToRootist true, ist dies root; Andernfalls ist es das Stammverzeichnis der aufgeblasenen XML-Datei.

Nun zum Beispiellayout und Code.

Hauptlayout ( main.xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</LinearLayout>

In diesen Container wird eine separate Textansicht eingefügt, die als kleines rotes Quadrat angezeigt wird, wenn Layoutparameter erfolgreich aus XML ( red.xml) angewendet werden :

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="25dp"
    android:layout_height="25dp"
    android:background="#ff0000"
    android:text="red" />

Wird jetzt LayoutInflatermit verschiedenen Variationen von Aufrufparametern verwendet

public class InflaterTest extends Activity {

    private View view;

    @Override
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);

      setContentView(R.layout.main);
      ViewGroup parent = (ViewGroup) findViewById(R.id.container);

      // result: layout_height=wrap_content layout_width=match_parent
      view = LayoutInflater.from(this).inflate(R.layout.red, null);
      parent.addView(view);

      // result: layout_height=100 layout_width=100
      view = LayoutInflater.from(this).inflate(R.layout.red, null);
      parent.addView(view, 100, 100);

      // result: layout_height=25dp layout_width=25dp
      // view=textView due to attachRoot=false
      view = LayoutInflater.from(this).inflate(R.layout.red, parent, false);
      parent.addView(view);

      // result: layout_height=25dp layout_width=25dp 
      // parent.addView not necessary as this is already done by attachRoot=true
      // view=root due to parent supplied as hierarchy root and attachRoot=true
      view = LayoutInflater.from(this).inflate(R.layout.red, parent, true);
    }
}

Die tatsächlichen Ergebnisse der Parametervariationen sind im Code dokumentiert.

ÜBERSICHT: Das Aufrufen LayoutInflaterohne Angabe von root führt zu einem Anstieg des Anrufs, wobei die Layoutparameter aus dem XML ignoriert werden. Der Aufruf von inflate mit root ist nicht gleich nullund attachRoot=truelädt die Layoutparameter, gibt jedoch das Root-Objekt erneut zurück, wodurch weitere Layoutänderungen am geladenen Objekt verhindert werden (es sei denn, Sie finden es mit findViewById()). Die aufrufende Konvention, die Sie höchstwahrscheinlich verwenden möchten, lautet daher:

loadedView = LayoutInflater.from(context)
                .inflate(R.layout.layout_to_load, parent, false);

Um Hilfe bei der Layout - Probleme, die Layout - Inspektor ist sehr zu empfehlen.

andig
quelle
20
Hervorragende Antwort. Ich arbeite seit 3 ​​Jahren an Android und zähle und hatte noch etwas daraus zu lernen.
Reuben Scratton
Hallo, gibt es eine Möglichkeit, dasselbe mit Java-Code zu tun, anstatt mit R.layout aufzublasen? weil ich kein Layout habe. Ich habe die Ansicht mit Java-Code erstellt und möchte dieselbe Ansicht 300 Mal hinzufügen.
Raj
1
@andig: Activityist Unterklasse Contextund die Antwort der Beispiele sind in Umfang Activity, so macht es einfacher , ich ersetzt getBaseContext()mit , thiswie zum Zweck dieser Antwort, es ist gleichwertig.
Marcin Orlowski
5
Container hat layout_width und layout_height auf "match_parent" gesetzt; Dann sagt der Kommentar "// Ergebnis: layout_height = wrap_content layout_width = match_parent". Vermisse ich etw
Marian Paździoch
1
Vielen Dank für die Recherche und den Austausch der Ergebnisse! Außerdem stimme ich Marians Frage zu.
LarsH
5

andig ist richtig, dass ein häufiger Grund dafür, dass LayoutInflater Ihre layout_params ignoriert, darin besteht, dass kein Stamm angegeben wurde. Viele Leute denken, Sie können null für root übergeben. Dies ist für einige Szenarien akzeptabel, z. B. für ein Dialogfeld, in dem Sie zum Zeitpunkt der Erstellung keinen Zugriff auf root haben. Eine gute Regel ist jedoch, wenn Sie root haben, geben Sie es LayoutInflater.

Ich habe einen ausführlichen Blog-Beitrag darüber geschrieben, den Sie hier lesen können:

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

Seanjfarrell
quelle
1
This is acceptable for a few scenarios such as a dialogdas war alles was ich brauchte
rookieDeveloper
0


Ich möchte der Hauptantwort oben hinzufügen. Ich habe versucht, ihr zu folgen, aber mein recyclerView begann, jedes Element auf einen Bildschirm zu dehnen, den
ich nach dem Aufblasen in die nächste Zeile einfügen musste, um das Ziel zu erreichen

itemLayoutView.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT));

Ich habe diese Parameter bereits per XML hinzugefügt, aber es hat nicht richtig funktioniert
und mit dieser Zeile ist alles in Ordnung

Kirguduck
quelle