Apa tujuan dari tag <merge> Android dalam tata letak XML?

325

Saya sudah membaca posting Romain Guy di <merge />tag, tapi saya masih tidak mengerti bagaimana ini berguna. Apakah itu semacam penggantian <Frame />tag, atau digunakan seperti:

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

lalu <include />kode di file lain?

cesar
sumber

Jawaban:

586

<merge/> berguna karena dapat menghilangkan ViewGroup yang tidak dibutuhkan, yaitu tata letak yang hanya digunakan untuk membungkus pandangan lain dan tidak melayani tujuan itu sendiri.

Misalnya, jika Anda <include/>menggunakan tata letak dari file lain tanpa menggunakan penggabungan, kedua file tersebut mungkin terlihat seperti ini:

layout1.xml:

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

layout2.xml:

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

yang secara fungsional setara dengan tata letak tunggal ini:

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

FrameLayout di layout2.xml mungkin tidak berguna. <merge/>membantu menyingkirkannya. Inilah yang terlihat seperti menggunakan gabungan (layout1.xml tidak berubah):

layout2.xml:

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

Ini secara fungsional setara dengan tata letak ini:

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

tetapi karena Anda menggunakan <include/>Anda dapat menggunakan kembali tata letak di tempat lain. Itu tidak harus digunakan untuk mengganti hanya FrameLayouts - Anda dapat menggunakannya untuk mengganti tata letak yang tidak menambahkan sesuatu yang berguna dengan cara tampilan / perilaku Anda.

blazeroni
sumber
17
Dalam contoh ini Anda bisa membuat layout2.xml hanya berisi <TextView />, tidak ada yang lain.
Karu
21
Benar, TextView sederhana dapat digunakan sebagai gantinya di layout2, namun itu kemudian akan menjadi hal yang sangat berbeda dan tidak berguna sebagai contoh dalam jawaban untuk pertanyaan ini.
Dave
Sehubungan dengan tag <include>, selalu berguna untuk menggunakan tag <merge>.
Anshul
38
@Karu: Anda benar, tag gabungan tidak diperlukan dalam contoh ini, tetapi itu hanya karena ada satu elemen di layout2. Jika layout2 memiliki beberapa elemen, maka HARUS memiliki simpul root untuk menjadi XML yang valid dan saat itulah tag gabungan berguna.
gMale
3
Jadi bagaimana Anda menentukan apakah <merge> memiliki orientasi vertikal atau horizontal? Dan bagaimana Anda memberikan Lay_ Layout?
IgorGanapolsky
304

Tag sertakan

The <include>tag memungkinkan Anda untuk membagi tata letak Anda menjadi beberapa file: membantu berurusan dengan kompleks antarmuka pengguna atau terlalu lama.

Misalkan Anda membagi tata letak kompleks Anda menggunakan dua file sertakan sebagai berikut:

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>

Maka Anda perlu menulis include1.xmldan include2.xml.

Perlu diingat bahwa xml dari file include hanya dibuang di top_level_activitytata letak Anda pada waktu rendering (seperti #INCLUDEmakro untuk C).

File yang disertakan adalah tata letak jane polos 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"/>

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

Lihat? Tidak ada yang mewah. Perhatikan bahwa Anda masih harus mendeklarasikan namespace android dengan xmlns:android="http://schemas.android.com/apk/res/android.

Jadi versi rendering dari top_level_activity.xml adalah:

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

Dalam kode java Anda, semua ini transparan: findViewById(R.id.textView1)di kelas aktivitas Anda mengembalikan widget yang benar (bahkan jika widget itu dinyatakan dalam file xml berbeda dari tata letak aktivitas).

Dan ceri di atas: editor visual menangani hal itu dengan berenang. Tata letak tingkat atas dirender dengan xml disertakan.

Plotnya menebal

Karena file include adalah file xml layout klasik, itu berarti file tersebut harus memiliki satu elemen teratas. Jadi jika file Anda perlu memasukkan lebih dari satu widget, Anda harus menggunakan tata letak.

Katakanlah include1.xmlsekarang ada dua TextView: tata letak harus dideklarasikan. Mari kita pilih a 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>

The top_level_activity.xml akan diberikan sebagai:

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

Tapi tunggu dua level LinearLayoutitu mubazir !

Memang, dua bersarang LinearLayouttidak memiliki tujuan karena keduanya TextViewdapat dimasukkan di bawah layout1untuk rendering yang sama persis .

Jadi apa yang bisa kita lakukan?

Masukkan tag gabungan

The <merge>tag hanya tag boneka yang menyediakan elemen tingkat atas untuk menangani jenis masalah redundansi.

Sekarang include1.xml menjadi:

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

dan sekarang top_level_activity.xml diberikan sebagai:

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

Anda menyimpan satu tingkat hierarki, menghindari satu tampilan yang tidak berguna: Romain Guy sudah tidur lebih baik.

Apakah kamu tidak lebih bahagia sekarang?

Nama adalah carl
sumber
23
Deskripsi yang sangat baik.
RichieHH
4
menjelaskan dengan sangat jelas, harus dipilih sebagai jawabannya
lalitm
2
Luar biasa, tanpa keraguan ini harus menjadi jawaban yang diterima.
gaurav jain
1
tidak mengerti sesuatu .. bagaimana jika LinearLayout luar adalah vertikal misalnya, tetapi tampilan teks 2 di include1.xml seharusnya horizontal? penggabungan dalam kasus itu tidak menyimpan tata letak mereka yang saya inginkan. Apa yang bisa dilakukan?
Yonatan Nir
@YonatanNir menggabungkan bukan apa yang Anda butuhkan dalam kasus Anda, jelas. jika Anda benar-benar perlu meratakan hierarki tampilan, maka mungkin Anda dapat menggunakan RelativeLayoutatau menggambar tampilan secara manual
Abhijit
19

blazeroni sudah membuatnya cukup jelas, saya hanya ingin menambahkan beberapa poin.

  • <merge> digunakan untuk mengoptimalkan tata letak. Ini digunakan untuk mengurangi tidak perlu bersarang.
  • ketika tata letak yang berisi <merge>tag ditambahkan ke tata letak lain, <merge>simpul dihapus dan tampilan anaknya ditambahkan langsung ke induk baru.
Anshul
sumber
10

Untuk memiliki pengetahuan yang lebih mendalam tentang apa yang terjadi, saya membuat contoh berikut. Lihatlah file activity_main.xml dan content_profile.xml .

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>

Di sini, seluruh file tata letak ketika meningkat terlihat seperti ini.

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

Lihat bahwa ada LinearLayout di dalam induknya LinearLayout yang tidak melayani tujuan apa pun dan berlebihan. Melihat tata letak melalui alat Tata Letak Inspektur dengan jelas menjelaskan hal ini.

masukkan deskripsi gambar di sini

content_profile.xml setelah memperbarui kode untuk menggunakan gabungan alih-alih ViewGroup seperti 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>

Sekarang tata letak kita terlihat seperti ini

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

Di sini kita melihat bahwa ViewGroup LinearLayout yang berlebihan dihilangkan. Sekarang alat Layout Inspector memberikan hierarki tata letak berikut.

masukkan deskripsi gambar di sini

Jadi selalu mencoba menggunakan penggabungan ketika tata letak induk Anda dapat memposisikan tata letak anak Anda, atau lebih tepatnya menggunakan penggabungan ketika Anda memahami bahwa akan ada grup tampilan yang berlebihan dalam hierarki.

capt.swag
sumber
5

Alasan lain untuk menggunakan penggabungan adalah ketika menggunakan grup tampilan khusus di ListViews atau GridViews. Alih-alih menggunakan pola viewHolder dalam adaptor daftar, Anda dapat menggunakan tampilan kustom. Tampilan kustom akan mengembang xml yang root adalah tag gabungan. Kode untuk adaptor:

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

di sini adalah viewgroup khusus:

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

dan ini XML-nya:

<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>
mmienko
sumber
Apakah Anda menyiratkan bahwa jika Anda menggunakan RelativeLayout dalam file XML Anda dan ViewGroup kustom Anda diwarisi dari RelativeLayout, maka akan ada dua RelativeLayout, satu bersarang di yang lain?
Scott Biggs