XML düzenlerinde Android'in <merge> etiketinin amacı nedir?


325

Okuduğum Romain Guy yazı üzerine <merge />etiketi, ama hala yararlıdır anlamıyorum. <Frame />Etiketin bir tür değiştirilmesi mi yoksa şu şekilde mi kullanılır?

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

sonra <include />başka bir dosyada kod?

Yanıtlar:


586

<merge/> gereksizdir, çünkü diğer görünümleri sarmak ve hiçbir amaca hizmet etmemek için kullanılan düzenler gibi gereksiz ViewGroup'lardan kurtulabilir.

Örneğin, <include/>birleştirme kullanmadan başka bir dosyadan bir düzene gittiyseniz, iki dosya şöyle görünebilir:

layout1.xml:

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

layout2.xml:

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

işlevsel olarak bu tek düzene eşdeğerdir:

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

Layout2.xml dosyasındaki FrameLayout yararlı olmayabilir. <merge/>ondan kurtulmaya yardımcı olur. Birleştirme kullanmak gibi görünüyor (layout1.xml değişmez):

layout2.xml:

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

Bu, işlevsel olarak bu düzene eşdeğerdir:

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

ancak kullandığınız <include/>için düzeni başka bir yerde yeniden kullanabilirsiniz. Yalnızca FrameLayouts'un değiştirilmesi için kullanılmasına gerek yoktur - görünümünüzün görünümü / davranışı için yararlı bir şey eklemeyen herhangi bir düzeni değiştirmek için kullanabilirsiniz.


17
Bu örnekte layout2.xml dosyasının <TextView />başka hiçbir şey içermemesini sağlayabilirsiniz .
Karu

21
Doğru, düzen2'de bunun yerine basit bir TextView kullanılabilir, ancak bu tamamen farklı bir şey olur ve bu sorunun cevabında örnek olarak yararlı olmaz.
Dave

<include> etiketi ile birlikte <merge> etiketini kullanmak her zaman yararlıdır.
Anshul

38
@Karu: haklısınız, bu örnekte birleştirme etiketi gerekli değildir, ancak bunun nedeni yalnızca layout2'de bir öğe olmasıdır. Layout2 birden fazla öğeye sahipse, geçerli XML olması için bir kök düğüme sahip OLMALIDIR ve o zaman birleştirme etiketi işe yarar.
gMale

3
Peki <merge> 'in dikey yönlendirmesi mi yoksa yatay mı olduğunu nasıl belirlersiniz? Ve bir layout_weight nasıl verilir?
IgorGanapolsky

304

İçerme etiketi

<include>Etiketi, birden fazla dosya halinde düzeni bölmek için olanak sağlar: Bu uğraşan yardımcı karmaşık ya da gereğinden fazla kullanıcı arayüzü.

Diyelim ki iki yerleşim dosyasını kullanarak karmaşık mizanpajınızı şu şekilde böldünüz:

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>

Sonra yazmaya gerek include1.xmlve include2.xml.

Dan xml basitçe edilir dosyaları dahil olduğunu unutmayın dampingli sizin de top_level_activity(hemen hemen gibi oluşturma süresini de düzeni #INCLUDEC için makro).

Include dosyaları düz jane düzeni xml.

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"/>

... ve 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" />

Görmek? Hiçbir şey fantezi. Hala android ad alanını bildirmeniz gerektiğini unutmayın xmlns:android="http://schemas.android.com/apk/res/android.

Yani top_level_activity.xml dosyasının işlenmiş hali :

<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>

Java kodunuzda tüm bunlar şeffaftır: findViewById(R.id.textView1)etkinlik sınıfınızda doğru pencere öğesi döndürülür (bu pencere öğesi etkinlik düzeninden farklı bir xml dosyasında bildirilmiş olsa bile).

Ve üstteki kiraz: görsel editör şeyi yüzerek halleder. Üst düzey mizanpajı dahil xml ile oluşturulur .

Arsa kalınlaşıyor

İçerme dosyası klasik düzen xml dosyası olduğundan, bir üst öğeye sahip olması gerektiği anlamına gelir. Dolayısıyla, dosyanızın birden fazla widget içermesi gerekiyorsa, bir düzen kullanmanız gerekir.

Diyelim ki include1.xmlşimdi iki tane var TextView: bir düzen bildirilmelidir. Bir tane seçelim 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>

Top_level_activity.xml olarak sağlanacaktır:

<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>

Ama iki seviye LinearLayoutfazlalık bekleyin !

Gerçekten de, iç içe geçen iki, LinearLayouthiçbirine aynı renderleme için TextViewdahil edilebileceği için hiçbir amaca hizmet etmez .layout1

Öyleyse ne yapabiliriz?

Birleştirme etiketini girin

<merge>Etiket fazlalık sorunları bu tür başa bir üst düzey elemanı sağlar sadece bir kukla etikettir.

Şimdi include1.xml olur:

<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>

ve şimdi top_level_activity.xml şu şekilde işlenir:

<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>

Bir hiyerarşi seviyesi kaydettiniz, işe yaramayan bir görüşten kaçının: Romain Guy zaten daha iyi uyuyor.

Şimdi daha mutlu değil misin?


23
Mükemmel açıklama.
RichieHH

4
çok açık bir şekilde açıklıyor, cevap olarak seçilmelidir
lalitm

2
Mükemmel, şüphesiz bu kabul edilen cevap olmalı.
gaurav jain

1
bir şey anlamadı .. Ya dış LinearLayout dikey ise, ancak include1.xml dosyasındaki 2 metin görüntüsünün yatay olması gerekiyordu? bu durumda birleştirme istediğim düzenini kaydetmez. Bu konuda ne yapılabilir?
Yonatan Nir

@YonatanNir birleşmesi sizin durumunuzda ihtiyacınız olan şey değildir. görünüm hiyerarşisini gerçekten düzleştirmeniz gerekiyorsa, belki de RelativeLayoutgörünümleri manuel olarak kullanabilir veya çizebilirsiniz
Abhijit

19

blazeroni zaten oldukça netleştirdi, sadece birkaç nokta eklemek istiyorum.

  • <merge> Gereksiz yuvalamayı azaltmak için kullanılır.
  • <merge>etiketi içeren bir düzen başka bir düzene eklendiğinde, <merge>düğüm kaldırılır ve alt görünümü doğrudan yeni üst öğeye eklenir.

10

Olanlar hakkında daha derinlemesine bilgi sahibi olmak için aşağıdaki örneği oluşturdum. Activity_main.xml ve content_profile.xml dosyalarına bir göz atın .

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>

content_profile.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>

Burada, şişirildiğinde tüm düzen dosyası şöyle görünür.

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

Üst LinearLayout içinde hiçbir amaca hizmet etmeyen ve gereksiz olan bir LinearLayout bulunduğunu görün. Mizanpaj Müfettiş aracıyla düzene bir göz atmak bunu açıkça açıklar.

resim açıklamasını buraya girin

content_profile.xml , LinearLayout gibi bir ViewGroup yerine birleştirme kullanmak üzere kodu güncelledikten sonra content_profile.xml .

<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>

Şimdi düzenimiz şöyle görünüyor

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

Burada yedek LinearLayout ViewGroup'un kaldırıldığını görüyoruz. Şimdi Layout Inspector aracı aşağıdaki düzen hiyerarşisini verir.

resim açıklamasını buraya girin

Bu nedenle , ana düzeniniz çocuk mizanpajlarınızı konumlandırabildiğinde her zaman birleştirme kullanmaya çalışın veya hiyerarşide fazladan bir görünüm grubu olacağını anladığınızda daha kesin bir şekilde birleştirme kullanın .


5

Birleştirme kullanmanın bir başka nedeni, ListViews veya GridViews'de özel görünüm gruplarını kullanmaktır. Bir liste bağdaştırıcısında viewHolder desenini kullanmak yerine özel bir görünüm kullanabilirsiniz. Özel görünüm, kökü birleştirme etiketi olan bir xml'yi şişirir. Adaptör kodu:

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

İşte özel görünüm grubu:

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

ve işte 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>

Eğer bir XML dosyasında RelativeLayout kullanıldığında ima ediyorsunuz ve sonra da iki RelativeLayouts olacağını RelativeLayout miras özel ViewGroup, bir başka iç içe?
Scott Biggs
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.