Jaki jest cel znacznika Androida w układach XML?

Czytałempost Romain Guy na tag <merge />, ale nadal nie rozumiem, jak to jest przydatne. Jest to rodzaj zamiennika znacznika <Frame />, czy też jest używany w ten sposób:

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

Potem <include /> kod w innym pliku?

Author: David Snabel-Caunt, 2012-01-12

5 answers

<merge/> jest to przydatne, ponieważ może pozbyć się niepotrzebnych ViewGroups, tj. układów, które są po prostu używane do zawijania innych widoków i same nie służą żadnemu celowi.

Na przykład, jeśli masz <include/> układ z innego pliku bez użycia merge, oba pliki mogą wyglądać mniej więcej tak:

Layout1.xml:

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

Layout2.xml:

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

Który jest funkcjonalnie równoważny temu pojedynczemu układowi:

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

That FrameLayout in layout2.xml może nie być przydatny. Pomaga się go pozbyć. Oto jak to wygląda używając merge (layout1.xml nie zmienia się):

Layout2.xml:

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

Jest to funkcjonalnie równoważne temu układowi:

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

Ale ponieważ używasz <include/>, możesz ponownie użyć układu w innym miejscu. Nie musi być używany do zastąpienia tylko FrameLayouts - możesz go użyć do zastąpienia dowolnego układu, który nie dodaje czegoś użytecznego do sposobu, w jaki wygląda/zachowuje się twój widok.

 622
Author: blazeroni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-05 05:11:07

Znacznik include

The <include> tag pozwala podzielić układ na wiele plików: pomaga radzić sobie z złożonym lub nadmiernym interfejsem użytkownika.

Załóżmy, że dzielisz swój złożony układ za pomocą dwóch plików nagłówkowych w następujący sposób:

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>

Następnie należy napisać include1.xml i include2.xml.

Pamiętaj, że xml z plików nagłówkowych jest po prostu wrzucany do twojego top_level_activity układ w czasie renderowania (prawie jak makro #INCLUDE dla C).

Pliki nagłówkowe to zwykły układ 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"/>

... and 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" />
Widzisz? Nic wymyślnego. Zauważ, że nadal musisz zadeklarować przestrzeń nazw Androida za pomocą xmlns:android="http://schemas.android.com/apk/res/android.

Więc renderowana wersja top_level_activity.xml jest:

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

W Twoim kodzie Javy wszystko to jest przezroczyste: findViewById(R.id.textView1) w Klasa activity zwraca właściwy widżet (nawet jeśli widżet został zadeklarowany w pliku xml innym niż układ activity).

I wisienka na torcie: edytor wizualny radzi sobie z tym płynnie. Układ najwyższego poziomu jest renderowany z dołączonym xml.

Fabuła zagęszcza

Ponieważ plik include jest klasycznym plikiem XML układu, oznacza to, że musi mieć jeden górny element. Jeśli więc plik musi zawierać więcej niż jeden widżet, musiałby użyć układu.

Powiedzmy, że include1.xml ma teraz dwa TextView: układ musi być zadeklarowany. Wybierzmy 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 będzie renderowany jako:

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

ale poczekaj dwa poziomy {[17] } są zbędne !

Rzeczywiście, dwa zagnieżdżone LinearLayout nie służą żadnemu celowi, ponieważ dwa TextView mogą być zawarte w layout1dla dokładnie tak samo rendering .

Więc co możemy zrobić?

Wprowadź znacznik scalania

Znacznik <merge> jest tylko atrapą znacznika, który zapewnia najwyższy poziom elementu do radzenia sobie z tego rodzaju problemami redundancji.

Teraz include1.XML staje się:

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

A teraz top_level_activity.xml {[35] } jest renderowany jako:

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

Zachowałeś jeden poziom hierarchii, unikaj jednego bezużytecznego widoku: Romain Guy śpi już lepiej.

Nie jesteś teraz szczęśliwsza?
 333
Author: Name is carl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-18 22:27:09

Blazeroni już to wyjaśniłem, chcę tylko dodać kilka punktów.

  • <merge> służy do optymalizacji layouts.It służy do redukcji niepotrzebnego zagnieżdżania.
  • gdy układ zawierający znacznik <merge> jest dodawany do innego układu, węzeł <merge> jest usuwany, a jego widok potomny jest dodawany bezpośrednio do nowego rodzica.
 23
Author: Anshul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-03-26 10:08:17

Aby mieć bardziej dogłębną wiedzę o tym, co się dzieje, stworzyłem następujący przykład. Spójrz na activity_main.XML i content_profile.pliki 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>

Tutaj cały plik układu po napompowaniu wygląda tak.

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

Zobacz, że istnieje LinearLayout wewnątrz nadrzędnego LinearLayout, który nie służy żadnemu celowi i jest zbędny. Spojrzenie na narzędzie layout through Layout Inspector wyraźnie to wyjaśnia.

Tutaj wpisz opis obrazka

content_profile.xml po zaktualizowaniu kodu używać merge zamiast ViewGroup jak 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>

Teraz nasz layout wygląda tak

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

Tutaj widzimy, że redundantna LinearLayout ViewGroup jest usuwana. Teraz narzędzie Layout Inspector daje następującą hierarchię układu.

Tutaj wpisz opis obrazka

Więc zawsze staraj się używać merge gdy układ nadrzędny może pozycjonować układy potomne, lub dokładniej użyć merge gdy rozumiesz, że w hierarchii będzie nadmiarowa Grupa widoków.

 10
Author: capt.swag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-18 19:51:11

Innym powodem użycia scalania jest używanie niestandardowych grup widoków w ListViews lub GridViews. Zamiast używać wzorca viewHolder w adapterze listy, można użyć widoku niestandardowego. Widok niestandardowy nadmuchuje xml, którego głównym elementem jest znacznik scalania. Kod adaptera:

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

Oto niestandardowa Grupa widoków:

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

A oto 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>
 5
Author: mmienko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-08 06:03:13