Festlegen der ID bei Verwendung von Include in Layout-XML-Datei

117

In meine Layout-XML-Datei habe ich eine andere Layout-XML-Datei aufgenommen (jede mit einer anderen Android-ID).

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

Aber wenn ich es im Emulator ausführe und den Hierarchy Viewer starte, zeigt jedes Layout immer noch 'NO_ID' an, und in meinem Code habe ich findViewById(R.id.test1)undfindViewById(R.id.test2) beide geben null zurück.

Kann mir bitte jemand bei meinem Problem helfen?

hap497
quelle
6
Ihren IDs fehlt das @Symbol.
AutonomousApps

Antworten:

288

Geben Sie die ID in der an <include>

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

Verwenden Sie dann zwei, findViewByIdum auf Felder im Layout zuzugreifen

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

Mit diesem Ansatz können Sie auf jedes Feld in einem beliebigen Include zugreifen.

Ron Romero
quelle
18
Diese Methode gibt mir den Nullwert für das test1View-Objekt zurück.
Nirav Shah
4
Ich sehe den Unterschied nicht wirklich, können Sie erklären?
Goddchen
30
Ich habe herausgefunden, dass dies nicht hilft, wenn das von uns eingeschlossene Layout die Zusammenführung verwendet. Wenn jedoch keine Zusammenführung verwendet wird, funktioniert dies.
Zlatko
@Zlatko Yep, und das kann mergeauch theoretisch nicht funktionieren , da das Ergebnis des Einfügens von a mergenicht eine einzelne Ansicht ist, sondern eine Menge von ihnen. Also ist es OK.
Anzeigename
1
Dies funktioniert nur, wenn die Zusammenführung nicht verwendet wird. Im Falle einer Zusammenführung ist dies nicht möglich, wie hier angegeben: code.google.com/p/android/issues/detail?id=36918#c3
Zahid Rasheed
61

Ich habe herausgefunden, dass, wenn Sie ein <merge>Tag in Ihrem Include-Layout verwenden, die ID des Include auf das Merge-Tag übertragen wird, was keine echte Ansicht ist.

Entfernen Sie also entweder die Zusammenführung oder ersetzen Sie sie durch ein Layout.

Tor Norbye schrieb :

Das <include>Tag ist keine echte Ansicht, daher wird findByView es nicht finden. Das Attribut @id (und alle anderen Attribute, die Sie für das Include-Tag festgelegt haben) wird stattdessen auf das Root-Tag des Include-Layouts angewendet. Ihre activity.getView (R.id.included1) sollte also tatsächlich die <TextView>selbst sein.

loki19
quelle
3
Gut. Ich entferne das Zusammenführungs-Tag und es funktioniert, aber meine Frage hier ist, wie das Zusammenführungs-Tag verwendet wird, wenn ein Include-Layout ohne es funktioniert.
Ankur Chaudhary
35

Romain Guy gibt an, dass Sie die ID eines enthaltenen Layouts überschreiben können, indem Sie ein android:idAttribut in das <include>Tag einfügen.

<include android:id="@+id/cell1" layout="@layout/workspace_screen" />
Daniel Yankowsky
quelle
1
Das ist richtig. Der Verweis auf das Stammelement in der enthaltenen Layoutdatei erfolgt über die im Tag 'include' angegebene ID (sofern diese nicht angegeben ist).
Tom R
1
ID in <include> =
Roots
Wenn ich zuerst die ID setze (im Include-Tag überschreibt sie die ID aus dem enthaltenen Layout, oder?), Wird das Include-Tag zunächst als '@ + id / cell1' und dann als layout = 'angezeigt. @ layout / workspace_screen 'überschreibt die android: id erneut mit der ID des enthaltenen Layouts. @ Ron Romeros Antworten sind für mich sinnvoller.
Neon Warge
13

Ich denke, die Top-Antwort verfehlt den wichtigsten Punkt und könnte die Leute dazu verleiten, das zu denken <include/> Tag eine Ansicht erstellt, die den Include-Inhalt enthält.

Der entscheidende Punkt ist , dass die umfassen id ist vergangen an die Stammansicht der Includes Layout - Datei.

Das bedeutet, dass dies:

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

Wird dies:

// activity_main.xml
<ImageView
    android:id="@+id/someid"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    />
Andre Romano
quelle
4

Ja ist so, aber vorsichtig, wenn das in das Include-Feld eingefügte Layout ein benutzerdefiniertes ist und Sie auf dieses Root-Layout zugreifen möchten. Dieses Layout in diesem Fall @ layout / test test wird tatsächlich in der ersten Zeile zurückgegeben.

test test1View = (test)findViewById(R.id.test1);
Jokernk
quelle
2
  1. Sie müssen die ID für jedes Include-Tag festlegen
  2. enthaltenes untergeordnetes Element eine neue ID setzen. Wenn Sie nachsehen, wie Sie eine neue ID generieren können, sehen Sie sich diesen Eintrag an: https://stackoverflow.com/a/15442898/1136117
Sinan Ergin
quelle
2

Das Problem ist, dass wir versuchen, eine ID zu verwenden, die in der aktuellen Layoutdatei nicht deklariert ist. Anstatt erneut zu deklarieren, kann id einfach mit referenziert werden @+id/. Wenn Sie den ursprünglichen ID-Namen über Android Studio umgestalten, wird er auch im enthaltenen Layout umgestaltet.

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

Wenn Sie <RecyclerView>find verwenden, finden Sie die ID <include>von mithilfe einer Instanz der aufgeblasenen Ansicht, oder es wird null zurückgegeben .

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

Wenn Sie die ID entweder auf das Root-Tag des enthaltenen Layouts festgelegt haben, können Sie diese ID verwenden oder die ID auf das enthaltene Layout festlegen.

Sie können die ID jedoch nicht auf beide setzen, da dies eine Ausnahme auslösen kann.

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

Oder

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

Wenn Sie über Include sprechen, haben Sie entweder eine ID in der Stammansicht in der enthaltenen Layoutdatei oder in der Include-Zeile selbst und nicht in beiden. Beispielsweise:

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

Layout 1 Datei

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

Das obige Beispiel ist falsch, da technisch gesehen zwei IDs für dasselbe Layout deklariert sind. Sie müssen also auswählen, welches Element die ID haben soll.

mossman252
quelle
0

Wow, ich kann nicht glauben, dass diese Frage noch nicht die richtige Antwort hat. Es ist einfach Tags saugen. Sie können nur die Dinge ändern , die mit beginnen , android:layout_was android:idnicht übereinstimmt. Die Antwort ist also, dass Sie nicht können. Es tut uns leid. Stattdessen können Sie eine Klasse erstellen, die eine ViewGroup ist, die die darin enthaltenen Ansichten aufbläst, und diese dann als Tag in Ihr Layout einfügen, aber das war es auch schon.

TheHebrewHammer
quelle