web-dev-qa-db-fra.com

Comment faire en sorte que RelativeLayout fonctionne avec fusionner et inclure?

Depuis quelques jours, j'essaie de rendre mes mises en page plus efficaces en passant de plusieurs niveaux de LinearLayouts imbriqué à un RelativeLayout et j'ai rencontré quelques problèmes pour lesquels je n'ai pas trouvé de solution de contournement ...

J'ai effectué des recherches dans le groupe de débutants Android et sur ce site et je n'ai rien trouvé qui puisse m'aider à résoudre le problème.

J'ai lu sur l'un des blogs que vous pouvez combiner des mises en page avec des balises de fusion et d'inclusion. Donc, ce que j'ai est un fichier de mise en page principal avec un élément racine RelativeLayout. A l'intérieur de cela, j'ai 5 balises include qui font référence à 5 fichiers de présentation XML différents qui ont chacun un élément de fusion pour la racine (tous mes fichiers de fusion sont les mêmes, à l'exception de leurs identifiants). 

Je rencontre deux problèmes que j'expliquerai après la publication d'une version simplifiée de mon code de présentation:

Exemple de fichier de mise en page principal:

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

Exemple de fichier de fusion inclus:

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

Je rencontre deux problèmes:

1) Les attributs Android:layout_* semblent être ignorés lorsqu'ils sont utilisés dans la balise include et toutes les présentations fusionnées sont affichées les unes sur les autres. Selon ce message ( http://developer.Android.com/resources/articles/layout-tricks-reuse.html ) "tout attribut Android:layout_* peut être utilisé avec la balise <include />"

2) Etant donné que je ne pouvais pas faire fonctionner cela, j'ai décidé d'essayer d'ajouter un attribut Android:layout_below au premier élément TextView de chaque fichier de mise en forme de fusion, ce qui signifie que chaque fichier de fusion référencerait un identifiant provenant d'un autre fichier de mise en forme de fusion ... une partie de cette a effectivement travaillé et ma mise en page semble bien. Cependant, une erreur sur l'un des attributs Android:layout_below m'indique qu'elle ne trouve pas l'identifiant que j'ai spécifié ... J'ai vérifié les identifiants deux et trois fois pour m'assurer qu'ils étaient corrects. La partie la plus étrange est que j'ai utilisé la fonctionnalité AutoFill pour mettre l'identifiant dans l'attribut en premier lieu.

Si quelqu'un a des suggestions ou des solutions de contournement, je serai plus qu'heureux de les essayer. Aussi, si quelqu'un peut penser à un moyen pour moi d'avoir juste un fichier de mise en page de fusion xml au lieu de 5, cela serait grandement apprécié. Je ne pouvais pas trouver un moyen de le faire car je devais avoir accès à chaque élément des fichiers de mise en page fusionnés au moment de l'exécution ...

113
Justin

Il y a un problème avec la balise include. Vérifiez: https://issuetracker.google.com/issues/36908001

Pour résoudre ce problème, assurez-vous de remplacer BOTH layout_width et layout_height lors de l'inclusion, sinon tout sera ignoré.

211
Macarse

Voir la réponse plus votée ci-dessous. Le mien est terriblement obsolète


je peux répondre à un problème Justin soulevé: l'incapacité de RelativeLayout de gérer le positionnement d'un include (au moins dans ce cas simple, sur un émulateur 1.6)

CommonsWare suggère de regrouper les inclus dans un conteneur parent unique, mais cela afin d'aider à l'adressage et à la portée de vues de noms identiques dans - Justin's includes

Chacun devrait avoir un conteneur parent unique, et vous le feriez appelez findViewById () sur ce conteneur (ViewGroup) plutôt que sur le Activité.

En fait, vous devez également le faire afin que RelativeLayout se comporte comme prévu:

Cela fonctionne (footer _ est bien placé):

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

Cela ne fonctionne pas (pied de page _ flotte en haut de l'écran):

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

Le pied de page} include nu ne s'alignera pas au bas du parent, sans LinearLayout environnant .. Je n'appellerais pas ce comportement attendu.

De plus, la WebView semble bien s’attacher au en-tête par ID, mais j’estime qu’il s’agit d’une illusion, car elle passe simplement au-dessous de l’en-tête verticalement. J'ai également essayé de définir un bouton juste au-dessus du pied de page include, mais il est trop flatteur et faux

RelativeLayout a eu plus de problèmes en 1.5, mais je l'aime toujours :)

32
alienjazzcat

Mec, c'est vieux, mais il semble que ce soit la première des recherches, alors je vais faire un commentaire.

Je pense que l’astuce ici est que la balise <merge> combinée à la balise <include> supprime essentiellement tout type de groupe de vues "parent" à ce niveau. Alors, à qui demandez-vous exactement "layout_below" quelqu'un d'autre? Personne. Il n'y a pas de vue à ce niveau.

La balise <merge> prend les vues enfant et les insère directement dans le parent de la balise <include>. Vous devez donc demander aux enfants de la disposition que vous incluez de s’ancrer en conséquence.

7
Plantage

Pour que le positionnement fonctionne sur RelativeLayout, vous devez définir les paramètres layout_ * dans le fichier include et non dans le fichier de présentation principal. De cette façon

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>

Ce n’est évidemment pas ce que les développeurs veulent, mais c’est la seule solution que j’ai trouvée pour éviter la duplication xml

4
Maragues

Les attributs Android: layout_ * semblent à ignorer lorsqu’il est utilisé dans include balise et toutes les mises en page fusionnées sont affichés les uns sur les autres.

Mon hypothèse est que vous ne pouvez pas référencer, à partir de règles de mise en page, les attributs Android:id qui sont définis sur les éléments <include>, uniquement ceux qui se trouvent sur de "vrais" widgets et conteneurs.

Aussi, si quelqu'un peut penser à un moyen pour moi juste avoir une disposition de fusion xml fichier au lieu de 5 ce serait très appréciée.

Simple: mettez-les tous dans un seul fichier.

Je ne pouvais pas trouver un moyen de faire ça parce que je dois avoir accès à chaque élément dans la fusion des fichiers de mise en page à runtime

Que vous ayez un élément <include> ou 1 000, tout le contenu doit être accessible au moment de l'exécution. Une exception est si vous avez des attributs Android:id dupliqués - vous auriez besoin d'étendre correctement vos appels findViewById() pour obtenir le bon appel, comme vous le feriez pour obtenir des widgets à partir d'une ligne ListView.

Si vous pouvez créer un exemple de projet qui utilise 2 fichiers de fusion ou plus et où vous pouvez démontrer que le contenu est non accessible au moment de l'exécution, faites-le moi savoir.

1
CommonsWare

J'ai eu le même problème et même en définissant layout_width et layout_height cela n'a pas fonctionné . Le problème était que la mise en page que j'avais incluse avait des balises et qu'après les avoir supprimées, tout a fonctionné comme un charme . Je suppose que la fusion est pas une balise de mise en page et à cause de cela, il ne peut pas recevoir de paramètres de positionnement et de taille. Étant donné que tout ce que vous définissez est transféré dans la disposition parent interne, les paramètres ont été simplement supprimés.

TL: DR: Supprimez simplement les balises, déplacez les définitions xmlns vers un véritable détenteur de la vue et ça devrait aller.

Avant:

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

Travail:

<...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>
0
silvio.pereira

Dans mon cas, la mise en page que j'essayais d'inclure commence par la balise <merge. Quand je l'ai changé pour une disposition, disons <RelativeLayout cela a fonctionné. Ci-dessous, l'illustration.

TRAVAIL

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

Ne fonctionne pas 

<merge xmlns:tools="http://schemas.Android.com/tools"
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    tools:showIn="@layout/activity_home">
0
Rohit Mandiwal