Какова цель тега Android в XML-макетах?


Я читал пост Ромена Гая на <merge /> тег, но я до сих пор не понимаю, как это полезно. Это своего рода замена <Frame /> тег, или он используется так:

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

затем <include /> код в другом файле?

6 244

6 ответов:

<merge/> полезно, потому что он может избавиться от ненужных групп представлений, т. е. макетов, которые просто используются для обертывания других представлений и сами по себе не служат никакой цели.

например, если бы вы были <include/> макет из другого файла без использования слияния, два файла могут выглядеть примерно так:

layout1.XML-код:

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

layout2.XML-код:

<FrameLayout>
   <TextView />
</FrameLayout>

, который функционально эквивалентен одноместный макет:

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

что FrameLayout в layout2.xml может быть не полезен. <merge/> помогает избавиться от него. Вот как это выглядит с помощью merge (layout1.xml не меняется):

layout2.XML-код:

<merge>
   <TextView />
</merge>

это функционально эквивалентно этому макету:

<FrameLayout>
   <TextView />
</FrameLayout>

но так как вы используете <include/> вы можете использовать макет в другом месте. Он не должен использоваться для замены только FrameLayouts - вы можете использовать его для замены любого макета, который не является добавление чего-то полезного в то, как ваш взгляд выглядит/ведет себя.

включить тег

The <include> тег позволяет разделить макет на несколько файлов: это помогает справиться с комплекс или слишком длинный пользовательский интерфейс.

предположим, что вы разделили свой сложный макет с помощью двух файлов 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.xml и include2.xml.

имейте в виду, что xml от Include-файлы-это просто свалил в своем top_level_activity макет во время рендеринга (в значительной степени как #INCLUDE макрос для C).

файлы include-это обычный xml-файл Jane layout.

включают1.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" />

посмотреть? Ничего особенного. Обратите внимание, что вам все еще нужно объявить пространство имен android с помощью xmlns:android="http://schemas.android.com/apk/res/android.

так rendered версия top_level_activity.xml is:

<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) в вашем классе activity возвращает правильный виджет (даже если этот виджет был объявлен в xml-файле, отличном от макета activity).

и вишня на вершине:визуальный редактор обрабатывает штука, как по маслу. Макет верхнего уровня отображается С xml включенный.

интрига

Как включить файл является классическим XML-файл макета, это означает, что он должен иметь один верхний элемент. Поэтому, если ваш файл должен включать более одного виджета, вам придется использовать макет.

давайте, что include1.xml теперь TextView: макет должен быть объявлен. Давайте выберем LinearLayout.

включают1.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 будет отображаться как:

<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на точно такой же рендеринг.

так что же нам делать?

введите тег слияния

The <merge> тег - это просто фиктивный тег, который предоставляет элемент верхнего уровня для работы с такого рода проблемы с избыточностью.

теперь включают1.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 уже лучше спит.

а разве ты сейчас не счастлива?

простыми и точными словами,

когда макет, содержащий тег слияния, добавляется в другой макет, узел слияния удаляется, а его дочерние представления добавляются непосредственно в узел слияния. новый родитель.

объединить тег особенно полезно в сочетании с include tag, который используется для вставки содержимого одного формата в другой.

пример

<?xml version=”1.0” encoding=”utf-8”?>
<LinearLayout
xmlns:android=”http://schemas.android.com/apk/res/android”
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include android:id="@+id/my_id1"
layout="@layout/layout1"/>
<include android:id="@+id/my_id2"
layout="@layout/layout2"/>
</LinearLayout>

blazeroni уже довольно ясно, я просто хочу добавить несколько пунктов.

  • <merge> используется для оптимизации layouts.It используется для уменьшения ненужной вложенности.
  • когда макет, содержащий <merge> тег добавляется в другой макет,<merge> узел удаляется и его дочернее представление добавляется непосредственно к новому родителю.
  • <merge> тег особенно полезен с <include>, который используется для вставки содержимого других макет.

еще одна причина использовать слияние - это использование пользовательских групп представлений в 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;
    }
}

вот пользовательский viewgroup:

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>

чтобы иметь более глубокое знание того, что происходит, я создал следующий пример. Взгляните на 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 внутри родительского LinearLayout что не служит никакой цели и является избыточным. Взгляд на макет через инструмент инспектора макетов ясно объясняет это.

enter image description here

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 удаляется. Теперь инструмент инспектор макетов дает следующая иерархия макета.

enter image description here

поэтому всегда старайтесь использовать слияние когда ваш родительский макет может позиционировать ваши дочерние макеты, или более точно использовать слияние когда вы понимаете, что в иерархии будет избыточная группа представлений.