Comment spécifier l'ID lorsque les utilisations incluent dans le fichier XML de mise en page

117

Dans mon fichier xml de mise en page, j'ai inclus un autre fichier xml de mise en page (chacun avec un identifiant Android différent).

<include layout="@layout/view_contact_name" android:id="+id/test1"/>
<include layout="@layout/view_contact_name" android:id="+id/test2"/>

Mais lorsque je l'exécute dans l'émulateur et que je lance Hierarchy Viewer, chaque mise en page affiche toujours 'NO_ID', et dans mon code, j'ai findViewById(R.id.test1)et les findViewById(R.id.test2)deux retournent null.

Quelqu'un peut-il m'aider s'il vous plaît avec mon problème?

hap497
la source
6
Vos identifiants n'ont pas le @symbole.
AutonomousApps

Réponses:

288

Spécifiez l'ID dans le <include>

<include layout="@layout/test" android:id="@+id/test1" />

Utilisez ensuite deux findViewByIdpour accéder aux champs dans la mise en page

View test1View = findViewById(R.id.test1);
TextView test1TextView = (TextView) test1View.findViewById(R.id.text);

En utilisant cette approche, vous pouvez accéder à n'importe quel champ dans n'importe quel include que vous avez.

Ron Romero
la source
18
Cette méthode me renvoie une valeur nulle pour l'objet test1View.
Nirav Shah
4
Je ne vois pas vraiment la différence, pouvez-vous expliquer?
Goddchen
30
J'ai découvert que si la mise en page que nous avons incluse utilise la fusion, cela n'aidera pas. Mais dans le cas où la fusion n'est pas utilisée, cela fonctionne.
Zlatko
@Zlatko Oui, et cela ne peut pas fonctionner mergemême en théorie, car le résultat de l'inclusion d'une vue mergen'est pas une vue unique, mais un tas d'entre elles. Donc c'est d'accord.
Afficher le nom le
1
Cela ne fonctionnera que si la fusion n'est pas utilisée. En cas de fusion, cela n'est pas possible comme spécifié ici: code.google.com/p/android/issues/detail?id=36918#c3
Zahid Rasheed
61

J'ai découvert que si vous utilisez une <merge>balise dans votre mise en page d'inclusion, l'ID de l'inclusion est transféré vers la balise de fusion qui n'est pas une vue réelle.

Donc, supprimez la fusion ou remplacez-la par une mise en page.

Tor Norbye a écrit :

La <include>balise n'est pas une vue réelle, donc findByView ne la trouvera pas. L'attribut @id (et tous les autres attributs que vous avez définis sur la balise include) est appliqué à la place sur la balise racine de la mise en page incluse. Donc, votre activity.getView (R.id.included1) devrait en fait être <TextView>lui - même.

loki19
la source
3
Bon. Je supprime la balise de fusion et cela commence à fonctionner, mais ma question est de savoir quelle est l'utilisation de la balise de fusion, le cas échéant, la mise en page fonctionne sans elle?
Ankur Chaudhary
35

Romain Guy indique que vous pouvez remplacer l'ID d'une mise en page incluse en mettant un android:idattribut à l'intérieur de la <include>balise.

<include android:id="@+id/cell1" layout="@layout/workspace_screen" />
Daniel Yankowsky
la source
1
C'est correct. La manière de référencer l'élément racine dans le fichier de mise en page inclus est par l'id donné dans la balise 'include' (sauf s'il n'est pas donné).
Tom R
1
ID dans <include> = ID de la racine dans la mise en page incluse
Fadils
Il me semble que si je définis d'abord l'id (dans la balise include, il remplace l'id de la mise en page incluse, n'est-ce pas?), J'aurai la balise include pour être initialement '@ + id / cell1' et ensuite la mise en page = ' @ layout / workspace_screen 'remplacera à nouveau le android: id avec l'identifiant de la mise en page incluse. Les réponses de @Ron Romero ont plus de sens pour moi.
Neon Warge
14

Je pense que la première réponse passe à côté du point le plus important et pourrait induire les gens en erreur en leur faisant croire que la <include/>balise crée une vue qui contient le contenu d'inclusion.

Le point clé est que l' identifiant de l'inclusion est passé à la vue racine du fichier de mise en page de l'inclusion.

Cela signifie que ceci:

// activity_main.xml
<include layout="@layout/somelayout" android:id="@+id/someid"/>

// somelayout.xml
<?xml version="1.0" encoding="utf-8"?>
<ImageView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    />

Devient ceci:

// activity_main.xml
<ImageView
    android:id="@+id/someid"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    />
André Romano
la source
4

Oui, c'est comme ça, mais attention lorsque la mise en page insérée dans le champ d'inclusion est personnalisée et que vous souhaitez accéder à cette mise en page racine. Cette mise en page dans ce cas @ layout / test test, est en fait renvoyée en première ligne.

test test1View = (test)findViewById(R.id.test1);
jokernk
la source
2
  1. vous devez définir un identifiant pour chaque balise d'inclusion
  2. élément enfant inclus définir un nouvel identifiant. si vous regardez comment générer un nouvel identifiant, regardez cette entrée: https://stackoverflow.com/a/15442898/1136117
Sinan Ergin
la source
2

Le problème est que nous essayons d'utiliser un id qui n'est pas déclaré dans le fichier de mise en page actuel. Au lieu de déclarer à nouveau, id peut être simplement référencé en utilisant @+id/. Si vous refactorisez le nom de l'identifiant d'origine via Android Studio, il le refactorise également dans la disposition incluse.

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

<TextView
    android:id="@+id/txt_description"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    **android:layout_below="@+id/toolbar"**
    android:layout_marginTop="16dp"
    android:paddingLeft="8dp"
    android:paddingRight="8dp"/>
Prakash
la source
2

Dans un cas d'utilisation, <RecyclerView>recherchez l'id de <include>en utilisant une instance de vue gonflée, sinon il retournera null .

public class ViewHolder extends RecyclerView.ViewHolder {

        private mTextView;

        public ViewHolder(View view) {
            super(view);
            View include_1 = view.findViewById(R.id.include_1);
            mTextView = (TextView) include_1.findViewById(R.id.text_id);
        }
    }
Shanki Bansal
la source
1

Si vous avez défini id sur l'une des balises racine de la mise en page incluse, vous pouvez utiliser cet identifiant ou vous pouvez définir l'identifiant sur la mise en page incluse.

Mais vous ne pouvez pas définir id sur les deux, cela peut générer une exception.

<include layout="@layout/view_contact_name" android:id="+id/test1"/>

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

....
</LinearLayout>

Ou

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

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        android:id="@+id/llBottomMainView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

....
</LinearLayout>
Upendra Shah
la source
0

Lorsque vous parlez d'inclusion, vous avez soit un identifiant sur la vue racine à l'intérieur du fichier de mise en page inclus, soit sur la ligne d'inclusion elle-même et non sur les deux. Par exemple:

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

Fichier de mise en page 1

<RelativeLayout
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/layout2">

</RelativeLayout>

L'exemple ci-dessus est faux car techniquement, vous avez deux identifiants déclarés pour la même mise en page. Donc, ce que vous devez faire est de choisir quel élément aura l'id.

mossman252
la source
0

Wow, je ne peux pas croire que cette question n'ait pas encore la bonne réponse. Ce sont des balises simples, nulles. Vous ne pouvez changer que les choses qui commencent par celles android:layout_qui android:idne correspondent pas. Donc, la réponse est que vous ne pouvez pas. Désolé. Ce que vous pouvez faire à la place est de créer une classe qui sera un ViewGroup qui gonflera les vues incluses à l'intérieur, puis l'ajoutera en tant que balise dans votre mise en page, mais c'est à peu près tout.

TheHebrewHammer
la source