RelativeLayoutをマージおよびインクルードで機能させるにはどうすればよいですか?


114

私は数日間、ネストされた複数のレベルLinearLayoutsを1つに変換することでレイアウトをより効率的にするために試みておりRelativeLayout、回避策を見つけることができなかったいくつかの問題に遭遇しました...

私はAndroid初心者グループとこのサイトを検索しましたが、問題の解決に役立つ情報を見つけることができませんでした。

レイアウトを結合してタグを含めることができるブログの1つを読みました。だから私が持っているのはRelativeLayoutルート要素を持つメインレイアウトファイルです。その中に、ルートのマージ要素を持つ5つの異なるxmlレイアウトファイルを参照する5つのincludeタグがあります(私のマージファイルは、それらのIDを除いてすべて同じです)。

私は2つの問題に直面しています。レイアウトコードの簡略版を投稿した後で説明します。

メインレイアウトファイルの例:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@drawable/translucent_gray" >

    <include 
        android:id="@+id/running_gallery_layout_id"
        layout="@layout/running_gallery_layout" />

    <include 
        android:id="@+id/recent_gallery_layout_id" 
        layout="@layout/recent_gallery_layout"
        android:layout_below="@id/running_gallery_layout_id" />

    <include
        android:id="@+id/service_gallery_layout_id"
        layout="@layout/service_gallery_layout"
        android:layout_below="@id/recent_gallery_layout_id" />

    <include
        android:id="@+id/process_gallery_layout_id"
        layout="@layout/process_gallery_layout"
        android:layout_below="@id/service_gallery_layout_id" />

</RelativeLayout>

含まれているマージファイルの例:

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <TextView 
        style="@style/TitleText"
        android:id="@+id/service_gallery_title_text_id"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="left"
        android:text="@string/service_title" />

    <Gallery
        android:id="@+id/service_gallery_id"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:layout_below="@id/service_gallery_title_text_id" />

    <TextView 
        style="@style/SubTitleText"
        android:id="@+id/service_gallery_current_text_id"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/service_gallery_title_text_id"
        android:layout_above="@id/service_gallery_id" />
</merge>

2つの問題が発生しています。

1)android:layout_*includeタグで使用した場合、属性は無視されたように見え、マージされたレイアウトはすべて互いの上に表示されます。この投稿(http://developer.android.com/resources/articles/layout-tricks-reuse.html)によるandroid:layout_*と、<include />「タグで任意の属性を使用できます」

2)これを機能させることができなかったので、各マージレイアウトファイルのandroid:layout_below最初のTextViewアイテムに属性を追加してみることにしました。つまり、各マージファイルは別のマージレイアウトファイルのIDを参照することになります...ほとんどの場合、これは実際に機能し、私のレイアウトはうまく見えます。ただし、android:layout_below指定したIDが見つからないという属性の1つでエラーが発生します... IDが正しいことを確認するために、IDをダブルおよびトリプルでチェックしました。最も変わった部分はAutoFill、最初に属性にIDを配置する機能を使用したことです。

誰かが提案や回避策を持っているなら、私はそれらを試して幸せ以上のものになります。また、私が5つではなく1つのマージxmlレイアウトファイルを用意する方法を誰かが考えることができれば、それは大歓迎です。実行時にマージレイアウトファイルの各アイテムにアクセスする必要があるため、その方法を見つけることができませんでした...

回答:


214

includeタグに問題があります。チェック:https : //issuetracker.google.com/issues/36908001

、それを修正必ず上書き作るの両方にlayout_widthlayout_heightを含めたときに、それ以外のすべてのものは無視されます。


15
これは、他の方法では不要なレイアウトオブジェクトの作成を回避するため、承認済みのソリューションよりも優れたソリューションです。また、Android開発者によると、これは問題なく動作します。
mikołak

4
これは、<include />を別のレイアウトにパックするよりも簡単で、ハードコーディングが少なく、より最適化されたソリューションです。リストを操作する場合はどうするか考えてください。
teoREtik

2
これは受け入れられた答えよりもはるかにうまく機能します。どうもありがとう!そして... c'mon google、すでにこの問題を修正してください、これはBSです!:)
フェリペカルダス

2
@JeffAxelrod、LayoutInflaterソースコードは、ルート要素がマージタグの場合、残念ながらid、visibility、layout_ *のオーバーライドが適用されないことを示しています。XMLルートとしてビューを持つことができないので、そこに余分なViewGroupが必要です...
Rafael Nobre

13
うまくいきませんでした。私は両方を持っておりlayout_widthlayout_height自分のに着手しました<include>。私はまた、設定しようとしたlayout_widthlayout_height私には<merge>成功しなかったけど。何が欠けていますか?
dum4ll3

33

以下のより投票数の多い回答をご覧ください。私はひどく時代遅れです


Justinが提起した1つの問題に対処できます:RelativeLayoutがインクルードの位置を管理できない(少なくとも、この単純なケースでは、1.6エミュレータ上で)

CommonsWareは、インクルードを一意の親コンテナにラップすることを提案していますが、ジャスティンのインクルード内で同じ名前のビューのアドレス指定とスコープ指定を支援するためにそうしています。

それぞれに一意の親コンテナが必要であり、アクティビティではなくそのコンテナ(ViewGroup)でfindViewById()を呼び出します。

実際、RelativeLayoutが期待どおりに動作するようにするに、これも行う必要があります

これは機能します(フッターは適切に配置されています)。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="fill_parent">
    <include android:id="@+id/header" layout="@layout/header"
        android:layout_alignParentTop="true" />
    <WebView android:id="@+id/webView" android:layout_below="@id/header"
        android:background="#77CC0000" android:layout_height="wrap_content"
        android:layout_width="fill_parent" android:focusable="false" />
    <LinearLayout android:layout_alignParentBottom="true"
        android:layout_height="wrap_content" android:layout_width="fill_parent">
        <include android:id="@+id/footer" layout="@layout/footer" />
    </LinearLayout>
</RelativeLayout>

これはありません(フッターは画面の上部に表示されます)。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="fill_parent">
    <include android:id="@+id/header" layout="@layout/header"
        android:layout_alignParentTop="true" />
    <WebView android:id="@+id/webView" android:layout_below="@id/header"
        android:background="#77CC0000" android:layout_height="wrap_content"
        android:layout_width="fill_parent" android:focusable="false" />
    <include android:id="@+id/footer" layout="@layout/footer"
        android:layout_alignParentBottom="true" />
</RelativeLayout>

裸のフッターインクルードは、周囲のLinearLayoutがないと、親の下部に揃えられません。この予想される動作は呼び出せません。

さらに、WebView自体はIDによってヘッダーにうまく接続されているように見えますが、ヘッダーの下を垂直に流れるだけなので、これは幻想であると思います。私もフッターインクルードの真上にボタンを設定しようとしましたが、それもすべて浮いていて間違っていました

RelativeLayoutには1.5でさらに問題がありましたが、それでも好きです:)


2
私はそれを1増やし、それから@Macarseのコメントを見て戻ってきました。それが正しい方法です。
Jayshil Dave、2013

この誤解を招く答えを削除してください:(
Daniel Smith

8

これは古いですが、検索の上部に表示されるようですので、コメントします。

ここでの秘訣は、<merge>タグとタグを組み合わせると、<include>そのレベルのあらゆる種類の「親」ビューグループが基本的に削除されることです。それでは、他の誰かに「layout_below」を正確に求めるのは誰ですか。誰も。そのレベルではビューはありません。

<merge>タグは、子ビューを取り、右の親にそれらをポップ<include>タグ。したがって、含めるレイアウトの子に、それに応じてアンカーするよう依頼する必要があります。


4

配置をRelativeLayoutで機能させるには、メインレイアウトファイルではなく、インクルードファイルにlayout_ *パラメーターを設定する必要があります。そのように

main_layout.xml

<RelativeLayout
  android:id="@+id/header"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content">
   ....
</RelativeLayout>

<RelativeLayout 
  android:id="@+id/footer"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:layout_alignParentBottom="true">
    .....
</RelativeLayout>

<include layout="@layout/content_layout" />

content_layout.xml

<merge xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout
    android:id="@+id/content"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_above="@id/footer"
    android:layout_below="@id/header" >

    ....
</RelativeLayout>
</merge>

これは明らかに私たちの開発者が望んでいることではありませんが、xmlの重複を避けるために私が見つけた唯一の解決策です


1
なぜ賛成票がないのですか?これでうまくいきました。パラメータを必要としないレイアウトに含めることができるオブジェクトにパラメータを固定するのは好きではありませんが、LinLayの場合、RelLayのlayout_ *が無視されているようです。何か不足していますか?
QED 2012

1

android:layout_ *属性は、includeタグで使用すると無視されるようで、すべてのマージされたレイアウトが互いの上に表示されます。

私の推測では、要素にandroid:id定義されている属性はレイアウトルールから参照できず、<include>「実際の」ウィジェットやコンテナにある属性のみを参照できます。

また、私が5つではなく1つのマージxmlレイアウトファイルを用意する方法を誰かが考えることができれば、それは大歓迎です。

シンプル:すべてを1つのファイルに入れます。

実行時にマージレイアウトファイルの各アイテムにアクセスする必要があるため、その方法を見つけることができませんでした

<include>要素が1 つでも1,000でも、実行時にすべてのコンテンツにアクセスできる必要があります。1つの例外は、android:id属性が重複している場合ですfindViewById()。リストビュー行からウィジェットを取得するときと同じように、呼び出しを適切にスコープして正しいものを取得する必要があります。

実行時にコンテンツにアクセスできないことを示すことができる2つ以上のマージファイルを使用するサンプルプロジェクトを作成できる場合は、お知らせください。


1
長い目で見ると管理が難しいので、それらすべてを1つの大きなレイアウトファイルに配置したくありません...そのため、1つのマージファイルで1つのメインxmlを作成する可能性を求めました... IDが異なることを除いて、まったく同じレイアウトのルートとしてマージ要素を持つ5つのファイルがあります。実行時にそれらにアクセスできるように、私はそのようにしています。私のfindViewById()コールのスコープが私がやりたいことのようです。同じ呼び出しを複数回含めても、実行時にすべてのコンポーネントにアクセスできるように、その呼び出しをどのようにスコープしますか?
ジャスティン

1
ご返信ありがとうございます。調べてみます。それまでの間(そして、ここで私の無知を暴露しているかもしれません)、各includeタグを親コンテナーでラップしないと、RelativeLayoutを使用する目的が無効になりますか?RelativeLayoutの誇大宣伝はすべて、ネストされたレイアウトを回避することです...
Justin

3
私がそれについて尋ねた唯一の理由は、スペースを節約し、優れたデザインを考案することでした...レイアウトの再利用性についてここで読んだ:developer.android.com/resources/articles/…そしてそれは良い音だと思った。それを実装しようとしたときに、いくつかの問題が発生しました。現在、5つのレイアウトがあり、IDを除いて基本的に複製されています。そのため、レイアウトの再利用性が良い候補になると思いました。たぶんここで何かが足りないかもしれませんが、RelativeLayoutだけではないようです...
Justin

1
うわー...そうであることに感謝非常に役立ちます。一般的にあなたの応答はかなり役立つので、あなたがただ悪い日を過ごしているのかどうかはわかりませんが、私は単に、私が読んだ記事と、達成したいレイアウトに対する適切な解決策を見つけようとしています。
ジャスティン

1
「そして、真に再利用するために、カスタムのViewクラスの切り札を作成すると、次のようになります」と同意しました。基本的なレイアウトを使用する比較的簡単な方法があったとしても、私はそれをしたくなかっただけです...「あなたは「チュード-人々がそれに反応するときに驚かないでください-を可決しました。スナークが高くても、ポイントはまだ有効です。「ListViewの行に切り替える方がよい場合があります。」リストビューは私のアプリの外観では動作しません。市場に出ている私のアプリはAppSwipeです。私が何をしているのか知りたいのなら...
Justin

1

試してください:

<RelativeLayout xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android"
    tools:showIn="@layout/activity_home">

0

私の場合、含めようとしたレイアウトは<mergeタグで始まります。レイアウトに変更したら、<RelativeLayoutうまくいったと言います。以下はイラストです。

ワーキング

<RelativeLayout xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android"
    tools:showIn="@layout/activity_home">

動かない

<merge xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android"
    tools:showIn="@layout/activity_home">

これは、最適なソリューションではない別のネストされたレイヤーを作成します
Silvia H

0

私は同じ問題を抱えていたとさえ定義layout_widthし、layout_heightそれが動作しませんでした。問題は、私が含めていたレイアウトにタグがあり、それらを削除した後、すべてが魅力のように機能したことでした。mergeはレイアウトタグではないため、配置とサイズのパラメーターを受け取ることができないと思います。で定義したものはすべて内部の親レイアウトに転送されるため、設定は破棄されました。

TL:DR:タグを削除し、xmlns定義を実際のレイアウトビューホルダーに移動するだけで問題ありません。

前:

<merge
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <...ui.component.BorderCardView
        android:layout_width="112dp"
        android:layout_height="32dp"
        app:cardCornerRadius="4dp"
        app:cardUseCompatPadding="true">

        <ImageView
            android:layout_width="16dp"
            android:layout_height="16dp"
            android:src="@drawable/ic_logout"
            android:tint="@color/divider" />

    </...ui.component.BorderCardView>
</merge>

ワーキング:

<...ui.component.BorderCardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="112dp"
    android:layout_height="32dp"
    app:cardCornerRadius="4dp"
    app:cardUseCompatPadding="true">

    <ImageView
        android:layout_width="16dp"
        android:layout_height="16dp"
        android:src="@drawable/ic_logout"
        android:tint="@color/divider" />

</...ui.component.BorderCardView>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.