วัตถุประสงค์ของแท็ก <merge> ของ Android ในรูปแบบ XML คืออะไร


325

ฉันได้อ่านโพสต์ของ Romain Guyบน<merge />แท็กแล้ว แต่ฉันยังไม่เข้าใจว่ามันมีประโยชน์อย่างไร มันคือการเปลี่ยนประเภทของ<Frame />แท็กหรือใช้เป็นอย่างนั้น:

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

ดังนั้น<include />รหัสในไฟล์อื่น?

คำตอบ:


586

<merge/> มีประโยชน์เพราะสามารถกำจัด ViewGroups ที่ไม่จำเป็นออกไปเช่นโครงร่างที่ใช้เพื่อล้อมมุมมองอื่น ๆ

ตัวอย่างเช่นหากคุณไป<include/>ที่เลย์เอาต์จากไฟล์อื่นโดยไม่ใช้ผสานไฟล์ทั้งสองอาจมีลักษณะดังนี้:

layout1.xml:

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

layout2.xml:

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

ซึ่งเทียบเท่ากับรูปแบบเดียวกับหน้าที่:

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

FrameLayout นั้นใน layout2.xml อาจไม่มีประโยชน์ <merge/>ช่วยกำจัดมัน นี่คือสิ่งที่ดูเหมือนว่าการใช้ผสาน (layout1.xml จะไม่เปลี่ยนแปลง):

layout2.xml:

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

นี่คือหน้าที่เทียบเท่ากับเค้าโครงนี้:

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

แต่เนื่องจากคุณกำลังใช้<include/>คุณสามารถนำเค้าโครงมาใช้ที่อื่นได้ ไม่จำเป็นต้องใช้เพื่อแทนที่เฉพาะ FrameLayouts - คุณสามารถใช้เพื่อแทนที่เค้าโครงใด ๆ ที่ไม่ได้เพิ่มสิ่งที่มีประโยชน์กับวิธีการดู / พฤติกรรมของมุมมองของคุณ


17
ในตัวอย่างนี้คุณสามารถทำให้ layout2.xml มีเพียง<TextView />ไม่มีอะไรอื่น
Karu

21
จริงอยู่ TextView แบบธรรมดาสามารถใช้แทนใน layout2 ได้อย่างไรก็ตามนั่นจะเป็นสิ่งที่แตกต่างอย่างสิ้นเชิงและไม่มีประโยชน์อย่างเช่นในคำตอบของคำถามนี้
เดฟ

ใช้ร่วมกับแท็ก <include> มันจะมีประโยชน์เสมอที่จะใช้แท็ก <merge>
Anshul

38
@Karu: ถูกต้องแท็กผสานไม่จำเป็นในตัวอย่างนี้ แต่เป็นเพราะมีองค์ประกอบหนึ่งในเลย์เอาต์ 2 หาก layout2 มีองค์ประกอบหลายรายการก็ต้องมีรูทโหนดเพื่อเป็น XML ที่ถูกต้องและนั่นคือเมื่อแท็กผสานมีประโยชน์
gMale

3
ดังนั้นคุณจะระบุได้อย่างไรว่า <merge> มีการวางแนวตั้งหรือแนวนอน และคุณจะให้ layout_weight เป็นอย่างไร
IgorGanapolsky

304

แท็กรวม

<include>แท็กช่วยให้คุณสามารถที่จะแบ่งรูปแบบของคุณเป็นหลายไฟล์: มันจะช่วยให้การจัดการกับความซับซ้อนส่วนติดต่อผู้ใช้หรือยืดเยื้อ

สมมติว่าคุณแบ่งเลย์เอาต์ที่ซับซ้อนของคุณโดยใช้สองไฟล์รวมดังนี้:

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>

แล้วคุณจะต้องเขียนและinclude1.xmlinclude2.xml

โปรดทราบว่า xml จากไฟล์รวมนั้นจะถูกทิ้งในtop_level_activityเค้าโครงของคุณในเวลาที่แสดงผล (คล้ายกับ#INCLUDEแมโครสำหรับ C)

ไฟล์ include เป็นเลย์เอาต์ jane ธรรมดา

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

... และ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" />

ดู? ไม่มีอะไรแฟนซี โปรดทราบว่าคุณยังคงมีการประกาศ namespace xmlns:android="http://schemas.android.com/apk/res/androidหุ่นยนต์ที่มี

ดังนั้นเวอร์ชันที่แสดงผลของ 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 -->
    <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 ของคุณทั้งหมดนี้โปร่งใส: findViewById(R.id.textView1)ในคลาสกิจกรรมของคุณจะส่งคืนวิดเจ็ตที่ถูกต้อง (แม้ว่าวิดเจ็ตนั้นจะถูกประกาศในไฟล์ xml ที่แตกต่างจากโครงร่างกิจกรรม)

และเชอร์รี่อยู่ด้านบน: เครื่องมือแก้ไขภาพจัดการสิ่งที่ว่ายน้ำ เลย์เอาต์ระดับสูงสุดแสดงผลพร้อม xml ที่มีให้

โครงเรื่องหนาขึ้น

เนื่องจากไฟล์ include เป็นไฟล์ xml เลย์เอาต์แบบคลาสสิกหมายความว่าต้องมีองค์ประกอบด้านบนหนึ่งรายการ ดังนั้นในกรณีที่ไฟล์ของคุณต้องมีมากกว่าหนึ่งวิดเจ็ตคุณจะต้องใช้เลย์เอาต์

สมมติว่าinclude1.xmlตอนนี้มีสองTextView: เค้าโครงจะต้องมีการประกาศ ลองเลือก 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>

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

แต่รอสองระดับของLinearLayoutจะซ้ำซ้อน !

อันที่จริงทั้งสองซ้อนกันLinearLayoutเพื่อวัตถุประสงค์ใด ๆ ขณะที่ทั้งสองTextViewอาจจะรวมอยู่ภายใต้layout1สำหรับว่าการแสดงผลเดียวกัน

แล้วเราจะทำอย่างไร

ป้อนแท็กผสาน

<merge>แท็กเป็นเพียงแท็กหุ่นที่ให้องค์ประกอบระดับบนสุดที่จะจัดการกับชนิดของปัญหาความซ้ำซ้อนนี้

ตอนนี้include1.xmlกลายเป็น:

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

และตอนนี้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 --> 
    <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>

คุณบันทึกหนึ่งระดับลำดับชั้นหลีกเลี่ยงมุมมองที่ไร้ประโยชน์: Romain Guy นอนหลับได้ดีขึ้นแล้ว

ตอนนี้คุณมีความสุขมากกว่านี้ไหม


23
คำอธิบายที่ยอดเยี่ยม
RichieHH

4
อธิบายอย่างชัดเจนว่าควรเลือกให้เป็นคำตอบ
lalitm

2
ยอดเยี่ยมไม่ต้องสงสัยเลยว่านี่ควรเป็นคำตอบที่ยอมรับได้
gaurav jain

1
ไม่เข้าใจบางอย่าง .. ถ้า LinearLayout ด้านนอกเป็นแนวตั้งตัวอย่างเช่น แต่ textviews 2 ข้อความใน include1.xml ควรจะเป็นแนวนอน การรวมในกรณีนั้นไม่ได้บันทึกเค้าโครงที่ฉันต้องการ สิ่งที่สามารถทำได้เกี่ยวกับมัน?
Yonatan Nir

@YonatanNir ผสานไม่ใช่สิ่งที่คุณต้องการในกรณีของคุณอย่างชัดเจน ถ้าคุณจำเป็นต้องทำให้ลำดับการดูเป็นจริงขึ้นมาบางทีคุณอาจใช้RelativeLayoutหรือวาดมุมมองด้วยตนเอง
Abhijit

19

blazeroniทำให้มันชัดเจนแล้วฉันต้องการเพิ่มบางจุด

  • <merge> ใช้สำหรับปรับเค้าโครงให้เหมาะสมมันใช้สำหรับลดการซ้อนที่ไม่จำเป็น
  • เมื่อเลย์เอาต์ที่มี<merge>แท็กถูกเพิ่มเข้าไปในเลย์เอาต์อื่น<merge>โหนดจะถูกลบและมุมมองลูกของมันจะถูกเพิ่มโดยตรงไปยังผู้ปกครองใหม่

10

เพื่อให้มีความรู้เชิงลึกมากขึ้นว่าเกิดอะไรขึ้นฉันจึงสร้างตัวอย่างต่อไปนี้ มีลักษณะที่เป็นactivity_main.xmlและ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>

ในที่นี่ไฟล์เลย์เอาต์ทั้งหมดเมื่อขยายเกินจริงจะมีลักษณะเช่นนี้

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

ดูว่ามี LinearLayout อยู่ใน parentLayout หลักซึ่งไม่ได้ทำหน้าที่ใด ๆ และซ้ำซ้อน ดูที่รูปแบบผ่านเครื่องมือตรวจสอบเค้าโครงอธิบายอย่างชัดเจน

ป้อนคำอธิบายรูปภาพที่นี่

content_profile.xmlหลังจากอัปเดตรหัสเพื่อใช้ผสานแทนที่จะเป็น ViewGroup เช่น 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>

ตอนนี้เค้าโครงของเรามีลักษณะดังนี้

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

ที่นี่เราเห็นว่ามีการลบ LinearLayout ViewGroup ที่ซ้ำซ้อนออก เครื่องมือตรวจสอบเค้าโครงตอนนี้ให้ลำดับชั้นเค้าโครงต่อไปนี้

ป้อนคำอธิบายรูปภาพที่นี่

ดังนั้นให้ลองใช้การผสานเมื่อเค้าโครงแม่ของคุณสามารถวางตำแหน่งลูกของคุณหรือใช้การผสานอย่างแม่นยำมากขึ้นเมื่อคุณเข้าใจว่าจะมีกลุ่มมุมมองที่ซ้ำซ้อนในลำดับชั้น


5

อีกเหตุผลที่ควรใช้การผสานคือเมื่อใช้กลุ่มการดูที่กำหนดเองใน ListViews หรือ GridViews แทนที่จะใช้รูปแบบ viewHolder ในอะแดปเตอร์รายการคุณสามารถใช้มุมมองที่กำหนดเอง มุมมองที่กำหนดเองจะขยาย XML ที่รูทเป็นแท็กผสาน รหัสสำหรับอะแดปเตอร์:

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

นี่คือกลุ่มการดูที่กำหนดเอง:

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

และนี่คือ 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>

คุณหมายถึงว่าถ้าคุณใช้ RelativeLayout ในไฟล์ XML ของคุณและ ViewGroup ที่คุณกำหนดเองที่สืบทอดมาจาก RelativeLayout นั้นจะมี RelativeLayout สองอันหนึ่งซ้อนกันหรือไม่
Scott Biggs
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.