Zunächst einmal: Ja, ich habe alle anderen Threads zu diesem Thema gelesen. Und nicht nur die von dieser Seite ... (Sie sind ein bisschen frustriert)
Bei den meisten von ihnen wird empfohlen, Android:id
anstelle von id
in der XML-Datei zu verwenden. Ich tat.
Von anderen habe ich erfahren, dass View.findViewById
anders arbeitet als Activity.findViewById
. Das habe ich auch gemacht.
In meinem location_layout.xml
verwende ich:
<FrameLayout .... >
<some.package.MyCustomView ... />
<LinearLayout ... >
<TextView ...
Android:id="@+id/txtLat" />
...
</LinearLayout>
</FrameLayout>
In meiner Tätigkeit mache ich:
...
setContentView( R.layout.location_layout );
und in meiner benutzerdefinierten Ansichtsklasse:
...
TextView tv = (TextView) findViewById( R.id.txtLat );
was null
zurückgibt. Auf diese Weise funktioniert meine Aktivität gut. Vielleicht liegt es an den Unterschieden Activity.findViewById
und View.findViewById
. Also habe ich den Kontext gespeichert, der lokal an den Konstruktor für die Zollansicht übergeben wurde, und versuchte es:
...
TextView tv = (TextView) ((Activity) context).findViewById( R.id.txtLat );
was auch null
zurückgegeben hat.
Dann habe ich meine benutzerdefinierte Ansicht geändert, um ViewGroup
statt View
zu erweitern, und location_layout.xml
so geändert, dass TextView
ein direktes untergeordnetes Element meiner benutzerdefinierten Ansicht ist, sodass View.findViewById
wie erwartet funktionieren sollte. Überraschung: es hat nichts gelöst.
Also, was zum Teufel mache ich falsch?
Ich freue mich über Kommentare.
das gibt null zurück
Möglicherweise weil Sie es zu früh anrufen. Warten Sie bis onFinishInflate()
. Hier ist ein Beispielprojekt , das ein benutzerdefiniertes View
zeigt, das auf seinen Inhalt zugreift.
Möglicherweise rufen Sie findViewById
auf, bevor Sie setContentView
? Aufrufen. Versuchen Sie in diesem Fall, findViewById
NACHaufzurufen setContentView
.
Stellen Sie sicher, dass Sie nicht mehrere Versionen Ihres Layouts für unterschiedliche Bildschirmdichten haben. Ich habe dieses Problem einmal beim Hinzufügen einer neuen ID zu einem vorhandenen Layout festgestellt, habe aber vergessen, die HDpi-Version zu aktualisieren. Wenn Sie vergessen, alle Versionen der Layoutdatei zu aktualisieren, funktioniert sie für einige Bildschirmdichten, andere jedoch nicht.
In meinem Fall hatte ich zwei Aktivitäten in meinem Projekt, main.xml
und main2.xml
. Von Anfang an war main2
eine Kopie von main
, und alles funktionierte gut, bis ich main2
um neue TextView
fügte, sodass der R.id.textview1
für den Rest der App verfügbar wurde. Dann habe ich versucht, es per Standardruf abzurufen:
TextView tv = (TextView) findViewById( R.id.textview1 );
und es war immer null. Es stellte sich heraus, dass ich im onCreate
-Konstruktor nicht main2
, sondern den anderen instanziierte. Ich hatte:
setContentView(R.layout.main);
anstatt
setContentView(R.layout.main2);
Ich habe das bemerkt, als ich hier auf der Baustelle angekommen bin.
Neben den klassischen Ursachen, die an anderer Stelle erwähnt wurden:
setContentView()
aufgerufen haben, bevor findViewById()
id
in der Ansicht oder im Layout befindet, die Sie setContentView()
angegeben haben.id
nicht versehentlich in verschiedenen Layouts dupliziert wirdIch habe eine für benutzerdefinierte Ansichten in Standardlayouts gefunden, die der Dokumentation widerspricht:
Theoretisch können Sie eine benutzerdefinierte Ansicht erstellen und einem Layout hinzufügen ( siehe hier ). Ich habe jedoch herausgefunden, dass in solchen Situationen das id
-Attribut manchmal für alle Ansichten im Layout mit Ausnahme der benutzerdefinierten funktioniert. Die Lösung, die ich verwende, ist:
FrameLayout
mit den gleichen Layout-Eigenschaften, die Sie für die benutzerdefinierte Ansicht benötigen. Geben Sie ein entsprechendes id
an, sagen Sie frame_for_custom_view
.In onCreate
:
setContentView(R.layout.my_layout);
FrameView fv = findViewById(R.id.frame_for_custom_layout);
MyCustomView cv = new MyCustomView(context);
fv.addView(cv);
dadurch wird die benutzerdefinierte Ansicht in den Rahmen eingefügt.
FindViewById kann null sein, wenn Sie in einer benutzerdefinierten Ansicht den falschen Superkonstruktor aufrufen. Das ID-Tag ist Teil von attrs. Wenn Sie also attrs ignorieren, löschen Sie die ID.
Das wäre falsch
public CameraSurfaceView(Context context, AttributeSet attrs) {
super(context);
}
Das ist richtig
public CameraSurfaceView(Context context, AttributeSet attrs) {
super(context,attrs);
}
@Override
protected void onStart() {
// use findViewById() here instead of in onCreate()
}
Eine Antwort für diejenigen, die ExpandableListView verwenden und diese Frage basierend auf ihrem Titel ausführen.
Ich hatte diesen Fehler beim Versuch, als Teil einer ExpandableListView-Implementierung mit TextViews in meinen untergeordneten und Gruppenansichten zu arbeiten.
In Ihren Implementierungen der Methoden getChildView () und getGroupView () können Sie etwa Folgendes verwenden.
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) myContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.child_layout, null);
}
Ich habe dieses hier gefunden.
Ich bin relativ neu in Android/Eclipse. Ich habe versehentlich die UI-Komponente zu activity_main.xml
anstelle von fragment_main.xml
hinzugefügt. Ich habe einige Stunden gebraucht, um das herauszufinden ...
FWIW, ich sehe nicht, dass jemand dieses Problem so gelöst hat, wie ich es brauchte. Keine Beschwerden zur Kompilierzeit, aber zur Laufzeit habe ich eine Nullansicht erhalten und die Dinge in der richtigen Reihenfolge aufgerufen. Das ist, findViewById () after setContentView () . Das Problem stellte sich heraus, dass meine Ansicht in content_main.xml definiert ist, aber in meiner activity_main.xml fehlte mir diese eine Anweisung:
<include layout="@layout/content_main" />
Als ich das zu activity_main.xml hinzugefügt habe, kein NullPointer mehr.
Mein Fall ist keiner wie oben, keine Lösung hat funktioniert. Ich gehe davon aus, dass meine Ansicht zu tief in die Layout-Hierarchie war. Ich habe es eine Ebene höher gesetzt und es war nicht mehr null.
In meinem speziellen Fall habe ich versucht, einer ListView eine Fußzeile hinzuzufügen. Der folgende Aufruf in onCreate () gab null zurück.
TextView footerView = (TextView) placesListView.findViewById(R.id.footer);
Wenn Sie dies ändern, um die Fußzeilenansicht aufzublähen, anstatt sie anhand der ID zu finden, wurde dieses Problem behoben.
View footerView = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.footer_view, null, false);
Ich wollte nur meinen speziellen Fall hier einwerfen. Könnte jemandem weiterhelfen.
Ich habe die Direktive in meiner Android-Benutzeroberflächen-XML folgendermaßen verwendet:
Elternansicht:
<FrameLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:tag="home_phone"
Android:background="@color/colorPrimary">
...
<include
layout="@layout/retry_button"
Android:visibility="gone" />
Unteransicht (retry_button):
<com.foo.RetryButton
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@+id/retry"
Android:layout_gravity="center"
Android:orientation="vertical"
Android:layout_width="100dp"
Android:layout_height="140dp">
.findViewById (R.id.retry) würde immer null zurückgeben. Wenn ich die ID aus der untergeordneten Ansicht in das Include-Tag verschoben habe, funktionierte es.
Feste Eltern:
<FrameLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:tag="home_phone"
Android:background="@color/colorPrimary">
...
<include
layout="@layout/retry_button"
Android:id="@+id/retry"
Android:visibility="gone" />
Feststehendes Kind:
<com.foo.RetryButton
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_gravity="center"
Android:orientation="vertical"
Android:layout_width="100dp"
Android:layout_height="140dp">
In meinem Fall habe ich ExpandableListView verwendet und Android:transcriptMode="normal"
gesetzt. Dies führte dazu, dass nur wenige Kinder in der erweiterbaren Gruppe verschwanden, und ich bekam eine NULL-Ausnahme, wenn ich die Liste scrollen ließ.
Legen Sie den Aktivitätsinhalt aus einer Layoutressource fest Dh. setContentView(R.layout.basicXml)
;
Ich hatte zwei XML-Layouts für dieselbe Aktivität - eines im Hochformat und eines im Querformat. Natürlich hatte ich die ID eines Objekts in der XML-Landschaft geändert, hatte aber vergessen, die gleiche Änderung in der Portrait-Version vorzunehmen. Stellen Sie sicher, dass Sie beim Ändern eines XML-Codes dasselbe mit der anderen XML-Datei tun. Andernfalls wird keine Fehlermeldung angezeigt, wenn Sie das Programm ausführen/debuggen und die ID nicht finden, die Sie nicht geändert haben. Oh dumme Fehler, warum musst du mich so bestrafen?
Ich habe das gleiche Problem, aber ich denke, es lohnt sich, es mit Ihnen zu teilen ... Wenn Sie ViewById im benutzerdefinierten Layout suchen müssen, zum Beispiel:
public class MiniPlayerControllBar extends LinearLayout {
//code
}
sie können die Ansicht nicht im Konstruktor abrufen. __ Sie sollten findViewById aufrufen, nachdem die Ansicht aufgeblasen ist. __ Sie können onFinishInflate
überschreiben.
Ich hatte das gleiche Problem. Ich habe eine Drittanbieter-Bibliothek verwendet, mit der Sie ihren Adapter für eine GridView überschreiben und Ihr eigenes Layout für jede GridView-Zelle angeben können.
Endlich wurde mir klar, was los war. Eclipse verwendete immer noch die Layout-XML-Datei der Bibliothek für jede Zelle in der GridView, obwohl dies nicht angezeigt wurde. In meinem benutzerdefinierten Adapter wurde angegeben, dass die XML-Ressource aus meinem eigenen Projekt verwendet wurde, obwohl dies zur Laufzeit nicht der Fall war.
Ich habe also sichergestellt, dass sich meine benutzerdefinierten XML-Layouts und -IDs von denen in der Bibliothek unterscheiden, das Projekt gesäubert und dann die richtigen benutzerdefinierten Layouts in meinem Projekt gelesen haben.
Seien Sie vorsichtig, wenn Sie den Adapter einer Drittanbieter-Bibliothek überschreiben und Ihre eigene Layout-XML angeben, die der Adapter verwenden soll. Wenn Ihr Layout in Ihrem Projekt den gleichen Dateinamen wie das in der Bibliothek hat, kann ein wirklich schwer zu findender Fehler auftreten!
Zusätzlich zu den oben genannten Lösungen stellen Sie sicher, dasstools:context=".TakeMultipleImages"
im Layout ist derselbe Wert in der Datei mainfest.xml:Android:name=".TakeMultipleImages"
für dasselbe Aktivitätselement . Es tritt auf, wenn mit copy and paste eine neue Aktivität erstellt wird
Ich habe alles ausprobiert, aber nichts hat funktioniert. Also musste ich meine ImageView-Statik public static ImageView texture;
und dann texture = (ImageView) findViewById(R.id.texture_back);
machen. Ich denke nicht, dass es ein guter Ansatz ist.
In meinem Fall hatte ich das Layout aufgeblasen, aber die untergeordneten Ansichten gaben null zurück. Ursprünglich hatte ich folgendes:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_history);
footerView = ((LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.listview_footer, null, false);
pbSpinner = (ProgressBar) findViewById(R.id.pbListviewFooter);
tvText = (TextView) findViewById(R.id.tvListviewFooter);
...
}
Als ich jedoch Folgendes geändert habe, hat es funktioniert:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_history);
footerView = ((LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.listview_footer, null, false);
pbSpinner = (ProgressBar) footerView.findViewById(R.id.pbListviewFooter);
tvText = (TextView) footerView.findViewById(R.id.tvListviewFooter);
...
}
Der Schlüssel bestand darin, das bereits aufgeblähte Layout gezielt zu referenzieren, um die untergeordneten Ansichten zu erhalten. Das heißt, footerView
hinzufügen:
In meinem Fall gab findViewById null zurück, wenn ich den Aufruf von einem übergeordneten Objekt in ein vom übergeordneten instanziierten Adapterobjekt verschob. Nachdem ich die hier aufgeführten Tricks ohne Erfolg versucht hatte, verschob ich die findViewById wieder in das übergeordnete Objekt und übergab das Ergebnis als Parameter während der Instantiierung des Adapterobjekts. Zum Beispiel habe ich dies in einem übergeordneten Objekt gemacht:
Spinner hdSpinner = (Spinner)view.findViewById(R.id.accountsSpinner);
Dann habe ich den hdSpinner als Parameter bei der Erstellung des Adapterobjekts übergeben:
mTransactionAdapter = new TransactionAdapter(getActivity(),
R.layout.transactions_list_item, null, from, to, 0, hdSpinner);
Mein Fix war, das Projekt einfach zu reinigen.
findViewById kann auch null zurückgeben, wenn Sie sich in einem Fragment befinden. Wie hier beschrieben: findViewById in Fragment
Sie sollten getView () aufrufen, um die oberste Ansicht innerhalb eines Fragments zurückzugeben. Dann finden Sie die Layoutelemente (Schaltflächen, Textansichten usw.).
Nach meiner Erfahrung scheint dies auch der Fall zu sein, wenn Ihr Code nach OnDestroyView aufgerufen wird (wenn sich das Fragment auf dem Back-Stack befindet.) Wenn Sie die Benutzeroberfläche mit der Eingabe eines BroadCastReceiver aktualisieren, sollten Sie überprüfen, ob dies der Fall ist .
DAS LAYOUT AUFFLASCHEN !! (welche die id enthält)
In meinem Fall hat findViewById () null zurückgegeben, weil das Layout, in dem das Element geschrieben wurde, nicht aufgeblasen wurde ...
ZB . Fragment_layout.xml
<ListView
Android:id="@+id/listview">
findViewById (R.id.listview) gab null zurück, da ich nicht getan hatte inflater.inflate (R.layout.fragment_layout, ..., ...); bevor.
Hoffe, diese Antwort hilft einigen von euch.
Es stürzte für mich ab, weil eines der Felder in meiner Aktivitäts-ID mit der ID in einer anderen Aktivität übereinstimmte. Ich habe es mit einer eindeutigen ID behoben.
In meiner loginActivity.xml-Kennwortfeld-ID war "Kennwort" angegeben. In meiner Registrierungsaktivität habe ich es einfach korrigiert, indem ich die ID r_password angegeben habe. Dann wurde kein Objekt zurückgegeben:
password = (EditText)findViewById(R.id.r_password);
Ich hatte ein ähnliches Problem, als ich versuchte, eine benutzerdefinierte Ansicht für eine ListView
zu erstellen.
Ich habe es einfach so gelöst:
public View getView(int i, View view, ViewGroup viewGroup) {
// Gets the inflater
LayoutInflater inflater = LayoutInflater.from(this.contexto);
// Inflates the layout
ConstraintLayout cl2 = (ConstraintLayout)
inflater.inflate(R.layout.custom_list_view, viewGroup, false);
//Insted of calling just findViewById, I call de cl2.findViewById method. cl2 is the layout I have just inflated.
TextView tv1 = (TextView)cl2.findViewById(cl2);