web-dev-qa-db-ja.com

XMLレイアウトにおけるAndroidの<merge>タグの目的は何ですか?

<merge />タグの Romain Guyの投稿 を読んだことがありますが、それがどのように役立つのかまだわかりません。それは<Frame />タグの一種の置き換えですか、それともそのように使われますか:

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

<include />別のファイルのコード?

280
cesar

<merge/>は、不要なViewGroup、つまり単に他のビューをラップして目的を果たすために使用されるレイアウトを削除できるので便利です。

たとえば、マージを使用せずに別のファイルからレイアウトを<include/>する場合、2つのファイルは次のようになります。

layout1.xml:

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

layout2.xml:

<FrameLayout>
   <TextView />
</FrameLayout>

これは機能的にはこの単一のレイアウトと同等です。

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

Layout2.xmlのそのFrameLayoutは役に立ちません。 <merge/>はそれを取り除くのに役立ちます。これはmergeを使用した場合の外観です(layout1.xmlは変更されません)。

layout2.xml:

<merge>
   <TextView />
</merge>

これは機能的にこのレイアウトと同等です。

<FrameLayout>
   <TextView />
</FrameLayout>

しかし<include/>を使っているので、他の場所でレイアウトを再利用することができます。 FrameLayoutsだけを置き換えるのに使用する必要はありません - あなたのビューが見える/振る舞う方法に有用な何かを追加していないレイアウトを置き換えるためにそれを使うことができます。

521
blazeroni

Includeタグ

<include> タグを使用すると、レイアウトを複数のファイルに分割できます。complexまたは長すぎるユーザーインターフェイスを処理するのに役立ちます。

次のように2つのインクルードファイルを使用して複雑なレイアウトを分割したとしましょう。

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レイアウトでは単純にダンプされていることに注意してください(Cの#INCLUDEマクロとほとんど同じです)。

インクルードファイルは普通のジェーンレイアウト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"/>

... andinclude2.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で宣言する必要があります。

したがって、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ファイルで宣言されている場合でも)。

そして一番上のチェリー語:ビジュアルエディタは物事を水泳で扱います。最上位のレイアウトがレンダリングされますwith含まれているxml。

プロットが厚くなる

インクルードファイルは古典的なレイアウトのxmlファイルなので、トップエレメントが1つ必要です。そのため、ファイルに複数のウィジェットを含める必要がある場合は、レイアウトを使用する必要があります。

include1.xmlに2つのTextViewがあるとしましょう。レイアウトを宣言する必要があります。 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>

しかし、2つのレベルのLinearLayoutが冗長になるのを待ってください

実際、2つのLinearLayoutlayout1forの下に含めることができるため、2つのネストされたTextViewは無意味ですまったく同じレンダリング

それで私たちは何ができるでしょうか?

差し込みタグを入力

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

1つの階層レベルを保存し、1つの無用なビューを避けます。RomainGuyはすでによく眠っています。

あなたは今幸せではないですか?

268
Name is carl

blazeroniすでにそれをかなり明確にしています、私はちょうど少数のポイントを追加したいです。

  • <merge>は、レイアウトを最適化するために使用されます。不要なネスティングを減らすために使用されます。
  • <merge>タグを含むレイアウトを別のレイアウトに追加すると、<merge>ノードは削除され、その子ビューは新しい親に直接追加されます。
13
Anshul

マージを使用するもう1つの理由は、ListViewまたはGridViewでカスタムビューグループを使用するときです。リストアダプタで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>
5
mmienko

何が起こっているのかをより深く知るために、次の例を作成しました。 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

LinearLayoutのようなViewGroupの代わりにmergeを使用するようにコードを更新した後の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>

今私たちのレイアウトはこのようになります

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

ここで、冗長なLinearLayout ViewGroupが削除されたことがわかります。今すぐレイアウトインスペクタツールは次のレイアウト階層を与えます。

enter image description here

したがって、親レイアウトが子レイアウトを配置できる場合は常にmergeを使用するか、より正確にはmergeを使用してください。階層内に冗長なビューグループがあることを理解している場合

5
capt.swag