403 Stimmen

Welchen Zweck erfüllt der <merge>-Tag von Android in XML-Layouts?

Ich habe gelesen Romain Guys Beitrag über die <merge /> Tag, aber ich verstehe immer noch nicht, wie es nützlich ist. Ist es eine Art Ersatz für das <Frame /> Tag, oder wird es wie folgt verwendet:

<merge xmlns:android="....">
<LinearLayout ...>
    .
    .
    .
</LinearLayout>
</merge>

dann <include /> den Code in einer anderen Datei?

710voto

blazeroni Punkte 8110

<merge/> ist nützlich, weil es nicht benötigte ViewGroups loswerden kann, d.h. Layouts, die nur dazu dienen, andere Views zu umhüllen und selbst keinen Zweck erfüllen.

Zum Beispiel, wenn Sie <include/> ein Layout aus einer anderen Datei, ohne die Zusammenführung zu verwenden, könnten die beiden Dateien etwa so aussehen:

layout1.xml:

<FrameLayout>
   <include layout="@layout/layout2"/>
</FrameLayout>

layout2.xml:

<FrameLayout>
   <TextView />
   <TextView />
</FrameLayout>

das funktionell diesem einzigen Layout entspricht:

<FrameLayout>
   <FrameLayout>
      <TextView />
      <TextView />
   </FrameLayout>
</FrameLayout>

Das FrameLayout in layout2.xml ist möglicherweise nicht nützlich. <merge/> hilft, sie loszuwerden. So sieht es nach dem Zusammenführen aus (layout1.xml ändert sich nicht):

layout2.xml:

<merge>
   <TextView />
   <TextView />
</merge>

Dies ist funktionell gleichwertig mit diesem Layout:

<FrameLayout>
   <TextView />
   <TextView />
</FrameLayout>

aber da Sie die <include/> können Sie das Layout an anderer Stelle wiederverwenden. Es muss nicht verwendet werden, um nur FrameLayouts zu ersetzen - Sie können es verwenden, um jedes Layout zu ersetzen, das nichts Nützliches zum Aussehen/Verhalten Ihrer Ansicht beiträgt.

384voto

Name is carl Punkte 5623

Das Include-Tag

Le site <include> Tag ermöglicht es Ihnen, Ihr Layout in mehrere Dateien aufzuteilen: Es hilft beim Umgang mit complejo oder eine zu lange Benutzeroberfläche.

Nehmen wir an, Sie teilen Ihr komplexes Layout wie folgt in zwei Include-Dateien auf:

top_level_activity.xml :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layout1" 
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <!-- First include file -->
    <include layout="@layout/include1.xml" />

    <!-- Second include file -->
    <include layout="@layout/include2.xml" />

</LinearLayout>

Dann müssen Sie schreiben include1.xml y include2.xml .

Denken Sie daran, dass die xml aus den Include-Dateien einfach ist entsorgt in Ihrem top_level_activity Layout zur Rendering-Zeit (ziemlich genau wie die #INCLUDE Makro für C).

Die Include-Dateien sind ganz normale Layout-xml-Dateien.

include1.xml :

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/textView1"
    android:text="First include"
    android:textAppearance="?android:attr/textAppearanceMedium"/>

... und include2.xml :

<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/button1"
    android:text="Button" />

Sehen Sie? Nichts Ausgefallenes. Beachten Sie, dass Sie immer noch den Android-Namensraum deklarieren müssen mit xmlns:android="http://schemas.android.com/apk/res/android .

Also die gerendert Version von top_level_activity.xml ist:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layout1" 
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <!-- First include file -->
    <TextView
        android:id="@+id/textView1"
        android:text="First include"
        android:textAppearance="?android:attr/textAppearanceMedium"/>

    <!-- Second include file -->
    <Button
        android:id="@+id/button1"
        android:text="Button" />

</LinearLayout>

In Ihrem Java-Code ist dies alles transparent: findViewById(R.id.textView1) in Ihrer Aktivitätsklasse gibt das richtige Widget zurück (auch wenn dieses Widget in einer anderen Xml-Datei als das Aktivitätslayout deklariert wurde).

Und die Kirsche auf dem Sahnehäubchen: die visueller Editor handhabt die Sache mit Bravour. Das Layout der obersten Ebene wird gerendert mit die xml enthalten.

Die Handlung verdichtet sich

Da es sich bei einer Include-Datei um eine klassische Layout-xml-Datei handelt, bedeutet dies, dass sie ein oberstes Element enthalten muss. Falls Ihre Datei also mehr als ein Widget enthalten muss, müssen Sie ein Layout verwenden.

Nehmen wir an, dass include1.xml hat jetzt zwei TextView : ein Layout muss deklariert werden. Wählen wir ein LinearLayout .

include1.xml :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layout2" 
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textView1"
        android:text="Second include"
        android:textAppearance="?android:attr/textAppearanceMedium"/>

    <TextView
        android:id="@+id/textView2"
        android:text="More text"
        android:textAppearance="?android:attr/textAppearanceMedium"/>

</LinearLayout>

Le site top_level_activity.xml wird wie folgt wiedergegeben:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layout1" 
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <!-- First include file -->
    <LinearLayout 
        android:id="@+id/layout2" 
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

       <TextView
            android:id="@+id/textView1"
            android:text="Second include"
            android:textAppearance="?android:attr/textAppearanceMedium"/>

       <TextView
            android:id="@+id/textView2"
            android:text="More text"
            android:textAppearance="?android:attr/textAppearanceMedium"/>

   </LinearLayout>

     <!-- Second include file -->
   <Button
        android:id="@+id/button1"
        android:text="Button" />

</LinearLayout>

Aber warten Sie die beiden Ebenen der LinearLayout sind redundant !

In der Tat sind die beiden verschachtelten LinearLayout sind zwecklos, da die beiden TextView könnte aufgenommen werden unter layout1 für genau dieselbe Wiedergabe .

Was können wir also tun?

Geben Sie den Merge-Tag ein

Le site <merge> Tag ist nur ein Dummy-Tag, das ein Element der obersten Ebene darstellt, um diese Art von Redundanzproblemen zu lösen.

Jetzt include1.xml wird:

<merge xmlns:android="http://schemas.android.com/apk/res/android">

    <TextView
        android:id="@+id/textView1"
        android:text="Second include"
        android:textAppearance="?android:attr/textAppearanceMedium"/>

    <TextView
        android:id="@+id/textView2"
        android:text="More text"
        android:textAppearance="?android:attr/textAppearanceMedium"/>

</merge>

und jetzt top_level_activity.xml wird wiedergegeben als:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layout1" 
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <!-- First include file --> 
    <TextView
        android:id="@+id/textView1"
        android:text="Second include"
        android:textAppearance="?android:attr/textAppearanceMedium"/>

    <TextView
        android:id="@+id/textView2"
        android:text="More text"
        android:textAppearance="?android:attr/textAppearanceMedium"/>

    <!-- Second include file -->
    <Button
        android:id="@+id/button1"
        android:text="Button" />

</LinearLayout>

Sie haben eine Hierarchieebene eingespart und eine überflüssige Ansicht vermieden: Romain Guy schläft schon besser.

Bist du jetzt nicht glücklicher?

35voto

Anshul Punkte 8724

blazeroni bereits ziemlich deutlich gemacht, ich möchte nur ein paar Punkte hinzufügen.

  • <merge> wird zur Optimierung von Layouts verwendet, um unnötige Verschachtelungen zu reduzieren.
  • wenn ein Layout mit <merge> Tag in ein anderes Layout eingefügt wird, wird das <merge> Knoten wird entfernt und seine untergeordnete Ansicht wird direkt der neuen übergeordneten Ansicht hinzugefügt.

12voto

capt.swag Punkte 9734

Um eine genauere Vorstellung von den Vorgängen zu bekommen, habe ich das folgende Beispiel erstellt. Werfen Sie einen Blick auf die activity_main.xml y inhalt_profil.xml Dateien.

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <include layout="@layout/content_profile" />

</LinearLayout>

inhalt_profil.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Howdy" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Hi there" />

</LinearLayout>

Hier sieht die gesamte Layoutdatei nach dem Aufblasen wie folgt aus.

<LinearLayout>
    <LinearLayout>
        <TextView />
        <TextView />
    </LinearLayout>
</LinearLayout>

Sie sehen, dass es ein LinearLayout innerhalb des übergeordneten LinearLayouts gibt, das keinen Zweck erfüllt und überflüssig ist. Ein Blick auf das Layout mit dem Layout Inspector Tool erklärt dies deutlich.

enter image description here

inhalt_profil.xml nach der Aktualisierung des Codes zur Verwendung von Merge anstelle einer ViewGroup wie LinearLayout.

<merge xmlns:android="http://schemas.android.com/apk/res/android">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Howdy" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Hi there" />

</merge>

Unser Layout sieht nun wie folgt aus

<LinearLayout>
    <TextView />
    <TextView />
</LinearLayout>

Hier sehen wir, dass die überflüssige LinearLayout ViewGroup entfernt wird. Das Werkzeug Layout Inspector zeigt nun die folgende Layout-Hierarchie.

enter image description here

Versuchen Sie also immer, die zusammenführen wenn Ihr übergeordnetes Layout Ihre untergeordneten Layouts positionieren kann, oder genauer gesagt, verwenden Sie zusammenführen wenn Sie wissen, dass es eine redundante Sichtengruppe in der Hierarchie geben wird.

6voto

mmienko Punkte 81

Ein weiterer Grund für die Verwendung der Zusammenführung ist die Verwendung benutzerdefinierter Ansichtsgruppen in ListViews oder GridViews. Anstatt das viewHolder Muster in einem Listenadapter zu verwenden, kann man einen benutzerdefinierten View verwenden. Der benutzerdefinierte View würde eine xml aufblasen deren Root ein Merge Tag ist. Code für den Adapter:

public class GridViewAdapter extends BaseAdapter {
     // ... typical Adapter class methods
     @Override
     public View getView(int position, View convertView, ViewGroup parent) {
        WallpaperView wallpaperView;
        if (convertView == null)
           wallpaperView = new WallpaperView(activity);
        else
            wallpaperView = (WallpaperView) convertView;

        wallpaperView.loadWallpaper(wallpapers.get(position), imageWidth);
        return wallpaperView;
    }
}

Hier ist die benutzerdefinierte Ansichtsgruppe:

public class WallpaperView extends RelativeLayout {

    public WallpaperView(Context context) {
        super(context);
        init(context);
    }
    // ... typical constructors

    private void init(Context context) {
        View.inflate(context, R.layout.wallpaper_item, this);
        imageLoader = AppController.getInstance().getImageLoader();
        imagePlaceHolder = (ImageView) findViewById(R.id.imgLoader2);
        thumbnail = (NetworkImageView) findViewById(R.id.thumbnail2);
        thumbnail.setScaleType(ImageView.ScaleType.CENTER_CROP);
    }

    public void loadWallpaper(Wallpaper wallpaper, int imageWidth) {
        // ...some logic that sets the views
    }
}

und hier ist das XML:

<merge xmlns:android="http://schemas.android.com/apk/res/android">

    <ImageView
        android:id="@+id/imgLoader"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_centerInParent="true"
        android:src="@drawable/ico_loader" />

    <com.android.volley.toolbox.NetworkImageView
        android:id="@+id/thumbnail"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</merge>

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X