findViewByID devuelve nulo

252

En primer lugar: sí, leí todos los otros hilos sobre este tema. Y no solo los de este sitio ... (ya ves, estoy un poco frustrado)

La mayoría de ellos vienen con el consejo de usar en android:idlugar de solo iden el archivo XML. Yo hice.

De otros, aprendí, eso View.findViewByIdfunciona de otra manera Activity.findViewById. Yo también manejé eso.

En mi location_layout.xml, yo uso:

<FrameLayout .... >
    <some.package.MyCustomView ... />

    <LinearLayout ... >
        <TextView ...
            android:id="@+id/txtLat" />
        ...
    </LinearLayout>
</FrameLayout>

En mi actividad hago:

...
setContentView( R.layout.location_layout );

y en mi clase de vista personalizada:

... 
TextView tv = (TextView) findViewById( R.id.txtLat );

que devuelve null. Al hacer esto, mi actividad funciona bien. Entonces quizás sea por las diferencias Activity.findViewByIdy View.findViewById. Así que almacené el contexto pasado al constructor de la vista de aduanas localmente e intenté:

...
TextView tv = (TextView) ((Activity) context).findViewById( R.id.txtLat );

que también regresó null.

Luego, cambié mi vista personalizada para ampliar en su ViewGrouplugar Viewy cambié location_layout.xmlpara permitir que TextViewsea ​​un hijo directo de mi vista personalizada, para que View.findViewByIdfuncione como se supone. Sorpresa: no resolvió nada.

Entonces, ¿qué diablos estoy haciendo mal?

Agradeceré cualquier comentario.

Thomas
fuente
66
Esto puede ocurrir si el proyecto también está dañado. Lo arreglé limpiando el proyecto
Pacerier
1
pasó la vista de contexto incorrecta gracias
izzy
1
@Pacerier gracias. Eso resolvió mi problema. Empiezo a odiar la programación de Android en Xamarin)
Artiom
@Pacerier "Proyecto limpio" también resolvió mi problema. Parece que Dropbox dañó el proyecto.
Kohki Mametani

Respuestas:

271

que devuelve nulo

Posiblemente porque lo estás llamando demasiado temprano. Esperar hasta onFinishInflate(). Aquí hay un proyecto de muestra que muestra un Viewacceso personalizado a sus contenidos.

CommonsWare
fuente
67
¡DIOS MIO! No puedo creer que pase días en algo tan trivial. Moví setContentView () sobre la llamada findViewById () y eso no fue el truco. ¡Gracias!
agentcurry
2
@CommonsWare que el proyecto correcto? No veo onFinishInflate en ningún lugar de github.com/commonsguy/cw-advandroid/tree/master/Animation/…
likejudo
1
@likejiujitsu: Podría haber tenido eso en 2010. He actualizado el enlace a un proyecto más nuevo que tiene onFinishInflate().
CommonsWare
3
Tengo mi setContentView llamado antes de findViewById y todavía es nulo. Estoy haciendo referencia a un EditText
Neon Warge
1
Enlace siempre a confirmaciones de GitHub fijas (por ejemplo, github.com/commonsguy/cw-omnibus/tree/… ) y nunca elimine repositorios o rebase ;-)
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
145

Posiblemente, ¿estás llamando findViewByIdantes de llamar setContentView? Si ese es el caso, intente llamar findViewById DESPUÉS de llamarsetContentView

Bayram Boyraz
fuente
1
Es un error tan fácil de cometer, pero desafortunadamente esto es lo que había hecho. El depurador no sirve de nada, ya que dijo que el error estaba en mi nueva línea de intención, no en la nueva actividad real que estaba llamando. ¡Gracias!
edude05
66
En realidad, tuve este error porque estaba llamando a setContentView apuntando a la vista incorrecta ... desafortunadamente, el compilador no detecta este tipo de error.
HeatfanJohn
Sí, eliminé setContentView por error y no entendí por qué mi programa comenzó a fallar.
Ronen Festinger
100

Asegúrese de no tener múltiples versiones de su diseño para diferentes densidades de pantalla. Me encontré con este problema una vez al agregar una nueva identificación a un diseño existente, pero olvidé actualizar la versión hdpi. Si olvida actualizar todas las versiones del archivo de diseño, funcionará para algunas densidades de pantalla pero no para otras.

Joe
fuente
8
¡GRACIAS! Eso fue todo. (En mi caso, tengo varias versiones para diferentes versiones de Android). Lo olvido todo el tiempo, aunque pongo un comentario gigantesco en la parte superior e inferior de cada archivo de diseño. Deseo que el compilador cometa un error o una gran advertencia si esto sucede.
tiktak
Ding ding ding, muchas gracias! Se inclinaba mi cerebro durante este lol
Zach
21

FindViewById puede ser nulo si llama al superconstructor incorrecto en una vista personalizada. La etiqueta de identificación es parte de los atributos, por lo que si ignora los atributos, elimine la identificación.

Esto estaría mal

public CameraSurfaceView(Context context, AttributeSet attrs) {
        super(context);
}

Esto es correcto

public CameraSurfaceView(Context context, AttributeSet attrs) {
        super(context,attrs);
}
repkap11
fuente
1
Muchas gracias señor! Tan descuidado que soy, incluso dudaba que hubiera algo mal con mi IDE. Qué suerte encontrar tu respuesta.
EffectiveMatrix
Cometí este error cuando creé mi vista personalizada. Gracias repkap11.
Andrew F.
15

En mi caso, tuve 2 actividades en mi proyecto, main.xmly main2.xml. Desde el principio, main2era una copia de main, y todo funcionaba bien, hasta que he añadido nuevo TextViewa main2, por lo que el R.id.textview1llegó a estar disponible para el resto de la aplicación. Luego traté de buscarlo mediante una llamada estándar:

TextView tv = (TextView) findViewById( R.id.textview1 );

y siempre fue nulo. Resultó que en el onCreateconstructor no estaba creando instancias main2, sino el otro. Yo tenía:

setContentView(R.layout.main);

en vez de

setContentView(R.layout.main2);

Me di cuenta de esto después de llegar aquí, en el sitio.

infografnet
fuente
14

Junto a las causas clásicas, mencionadas en otra parte:

  • Asegúrate de haber llamado setContentView()antesfindViewById()
  • Asegúrese de que lo idque desea está en la vista o diseño que le ha dado asetContentView()
  • Asegúrese de que idno se duplica accidentalmente en diferentes diseños

Hay una que he encontrado para vistas personalizadas en diseños estándar, que va en contra de la documentación:

En teoría, puede crear una vista personalizada y agregarla a un diseño ( ver aquí ). Sin embargo, descubrí que en tales situaciones, a veces el idatributo funciona para todas las vistas en el diseño, excepto las personalizadas. La solución que uso es:

  1. Reemplace cada vista personalizada con una FrameLayoutcon las mismas propiedades de diseño que le gustaría que tuviera la vista personalizada. Dale un apropiado id, por ejemplo frame_for_custom_view.
  2. En onCreate:

    setContentView(R.layout.my_layout);
    FrameView fv = findViewById(R.id.frame_for_custom_layout);
    MyCustomView cv = new MyCustomView(context);
    fv.addView(cv);

    que pone la vista personalizada en el marco.

Neil Townsend
fuente
Esto me ayudó: "Asegúrese de que la identificación que desea esté en la vista o diseño que le ha dado a setContentView ()". ¿Qué hacer cuando se trata de una subvista? Intenté obtener la vista principal y luego parentView.findById () pero todavía está volviendo nulo
NaturalBornCamper
@naturalborncamper si publicas una pregunta separada con un código de ejemplo, la echaré un vistazo.
Neil Townsend
Gracias Neil, ya publiqué y alguien señaló una mejor manera de hacer esto, aunque no funciona exactamente como debería ser, así que tuve que usar una estrategia diferente: stackoverflow.com/questions/47955376/…
NaturalBornCamper
9
    @Override
protected void onStart() {
         // use findViewById() here instead of in onCreate()
    }
Jonathan
fuente
6

Una respuesta para aquellos que usan ExpandableListView y se encuentran con esta pregunta según su título.

Tuve este error al intentar trabajar con TextViews en mi hijo y vistas grupales como parte de una implementación ExpandableListView.

Puede usar algo como lo siguiente en sus implementaciones de los métodos getChildView () y getGroupView ().

        if (convertView == null) {
            LayoutInflater inflater =  (LayoutInflater) myContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.child_layout, null);
        }

Encontré esto aquí .

Josh Metcalfe
fuente
5

Soy bastante nuevo en Android / Eclipse, por error agregué las cosas de la interfaz de usuario en activity_main.xmllugar de fragment_main.xml. Me tomó algunas horas resolver eso ...

lama12345
fuente
5

FWIW, no veo que nadie haya resuelto esto de la misma manera que yo necesitaba. No hubo quejas en el momento de la compilación, pero estaba obteniendo una vista nula en tiempo de ejecución y llamando las cosas en el orden correcto. Es decir, findViewById () después de setContentView (). El problema resultó que mi vista está definida en content_main.xml, pero en mi activity_main.xml, carecía de esta declaración:

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

Cuando agregué eso a activity_main.xml, no más NullPointer.

ferris
fuente
El problema con la copia al pegar un Fragmento es que a veces te olvidas de cambiar algunas cosas ... siendo el diseño correcto para inflar una de ellas. ¡Gracias!
Pablo Quemé
3

Yo tuve el mísmo problema. Estaba usando una biblioteca de terceros que le permite anular su adaptador para un GridView y especificar su propio diseño para cada celda GridView.

Finalmente me di cuenta de lo que estaba pasando. Eclipse todavía estaba usando el archivo xml de diseño de la biblioteca para cada celda en GridView, aunque no dio ninguna indicación de esto. En mi adaptador personalizado, indicaba que estaba usando el recurso xml de mi propio proyecto, aunque en tiempo de ejecución, no lo era.

Entonces, lo que hice fue asegurarme de que mis diseños e identificadores xml personalizados fueran diferentes de los que todavía estaban en la biblioteca, limpiaron el proyecto y luego comenzaron a leer los diseños personalizados correctos que estaban en mi proyecto.

En resumen, tenga cuidado si anula el adaptador de una biblioteca de terceros y especifica su propio diseño xml para que lo use el adaptador. Si su diseño dentro de su proyecto tiene el mismo nombre de archivo que el de la biblioteca, ¡es posible que encuentre un error realmente difícil de encontrar!

JDJ
fuente
3

En mi caso particular, estaba tratando de agregar un pie de página a ListView. La siguiente llamada en onCreate () estaba devolviendo nulo.

TextView footerView = (TextView) placesListView.findViewById(R.id.footer);

Cambiar esto para inflar la vista del pie de página en lugar de encontrarlo por ID resolvió este problema.

View footerView = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.footer_view, null, false);
Mate
fuente
2

En mi caso, estaba usando ExpandableListView y lo había configurado android:transcriptMode="normal". Esto estaba causando la desaparición de pocos niños en el grupo expandible y solía obtener una excepción NULL cuando usaba la lista.

Jeevan
fuente
2

Para mí, tenía dos diseños xml para la misma actividad: uno en modo vertical y otro en horizontal. Por supuesto, había cambiado la identificación de un objeto en el xml horizontal pero había olvidado hacer el mismo cambio en la versión vertical. Asegúrese de que si cambia uno, haga lo mismo con el otro xml o no recibirá un error hasta que lo ejecute / depure y no pueda encontrar la identificación que no cambió. Oh tontos errores, ¿por qué debes castigarme así?

ColosalChris
fuente
2

Establecer el contenido de la actividad de un recurso de diseño. es decir,. setContentView(R.layout.basicXml);

Ajay Takur
fuente
2

Además de las soluciones anteriores, se asegura
tools:context=".TakeMultipleImages" de que el diseño tenga el mismo valor en el archivo mainfest.xml:
android:name=".TakeMultipleImages"para el mismo elemento de actividad. ocurre cuando se usa copiar y pegar para crear una nueva actividad

usuario2982286
fuente
2

Tengo el mismo problema, pero creo que vale la pena compartirlo con ustedes. Si tiene que encontrar ViewById en un diseño personalizado, por ejemplo:

public class MiniPlayerControllBar extends LinearLayout {
    //code
}

No puede obtener la vista en constructor. Debe llamar a findViewById después de que la vista se haya inflado. Es un método que puede anularonFinishInflate

Shaw
fuente
2

Solo quería lanzar mi caso específico aquí. Podría ayudar a alguien en el futuro.

Estaba usando la directiva en mi UI XML de Android así:

Vista principal:

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

Vista secundaria (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) siempre devolvería nulo. Pero, si moví el ID de la vista secundaria a la etiqueta de inclusión, comenzó a funcionar.

Padre fijo:

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

Niño fijo:

<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">
John D.
fuente
2

Mi caso no es como el anterior, no funcionó ninguna solución. Supongo que mi punto de vista era demasiado profundo en la jerarquía de diseño. Lo subí un nivel y ya no era nulo.

Deividas Strioga
fuente
Tengo el mismo problema, también se puede encontrar un nivel más alto ... eso es bastante molesto y me gustaría saber por qué está sucediendo, ya que no puedo hacer mi menú como quiero
NaturalBornCamper
Bueno, las jerarquías de diseño profundas son antipatrón, casi siempre hay una solución más limpia. ¿Estás hablando del menú de desbordamiento en la barra de herramientas o el cajón de navegación?
Deividas Strioga
Cajón de navegación, ya publiqué otra pregunta en realidad, excepto que agregar un elemento de menú dentro de un grupo no funciona, solo lo agrega al final de todos los elementos: stackoverflow.com/questions/47955376/…
NaturalBornCamper
1

En mi caso, había inflado el diseño, pero las vistas secundarias estaban volviendo nulas. Originalmente tuve esto:

@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);
    ...
}

Sin embargo, cuando lo cambié a lo siguiente funcionó:

@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);
    ...
}

La clave era hacer referencia específica al diseño ya inflado para obtener las vistas secundarias. Es decir, para agregar footerView:

  • footerView .findViewById ...
Suragch
fuente
0

En mi experiencia, parece que esto también puede suceder cuando se llama a su código después de OnDestroyView (cuando el fragmento está en la pila posterior). Si está actualizando la IU en la entrada de un BroadCastReceiver, debe verificar si este es el caso .

Tad
fuente
0

¡INFLAR EL DISEÑO! (que contiene la identificación)

En mi caso, findViewById () devuelve nulo, porque el diseño en el que se escribió el elemento no se infló ...

P.ej. fragment_layout.xml

<ListView
android:id="@+id/listview">

findViewById (R.id.listview) devuelve nulo, porque no había hecho inflater.inflate (R.layout.fragment_layout, ..., ...); antes de eso.

Espero que esta respuesta ayude a algunos de ustedes.

ARCA
fuente
0

Mi solución fue simplemente limpiar el proyecto.

Liangjun
fuente
0

findViewById también puede devolver nulo si está dentro de un Fragmento. Como se describe aquí: findViewById en Fragment

Debe llamar a getView () para devolver la Vista de nivel superior dentro de un Fragmento. Luego puede encontrar los elementos de diseño (botones, vistas de texto, etc.)

tecnócrata
fuente
0

He intentado todo lo anterior, nada funcionaba ... así que tuve que hacer mi ImageView fuera estático public static ImageView texture; y luego texture = (ImageView) findViewById(R.id.texture_back);, no creo que sea un buen enfoque, pero esto realmente funcionó para mi caso :)

Tabish
fuente
lo siento, creo que la vista estática es mala idea
vuhung3990
0

En mi caso, findViewById devolvió nulo cuando moví la llamada de un objeto primario a un objeto adaptador instanciado por el padre. Después de probar los trucos enumerados aquí sin éxito, moví el findViewById nuevamente al objeto principal y pasé el resultado como un parámetro durante la creación de instancias del objeto adaptador. Por ejemplo, hice esto en el objeto padre:

 Spinner hdSpinner = (Spinner)view.findViewById(R.id.accountsSpinner);

Luego pasé el hdSpinner como parámetro durante la creación del objeto adaptador:

  mTransactionAdapter = new TransactionAdapter(getActivity(),
        R.layout.transactions_list_item, null, from, to, 0, hdSpinner);
Lexo
fuente
0

Se bloqueó para mí porque uno de los campos en mi id de actividad coincidía con el id en otra actividad. Lo arreglé dando una identificación única.

En mi contraseña de loginActivity.xml, la identificación del campo era "contraseña". En mi actividad de registro, simplemente lo arreglé dando la contraseña r_password, luego devolvió un objeto no nulo:

password = (EditText)findViewById(R.id.r_password);
Jageloo Yadav
fuente
0

Estaba enfrentando un problema similar cuando intentaba hacer una vista personalizada para a ListView.

Lo resolví simplemente haciendo esto:

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);
Rafael Costa
fuente
0

Formas de depurar y encontrar el problema:

  • Comente todos los findViewById en su actividad.
  • Comente todo excepto onCreate y setContentView
  • Ejecute el proyecto y vea si hay algún diseño establecido

En mi caso, estaba usando activity_main.xml tanto en mi módulo de aplicación como en mi módulo de biblioteca. Entonces, cuando realicé los pasos anteriores, en lugar del diseño que diseñé en la biblioteca, el diseño dentro del módulo de la aplicación se infló.

Así que cambié el nombre del archivo activity_main.xml a activity_main_lib.xml.

Así que asegúrese de no tener nombres de diseño duplicados en todo su proyecto .

Reejesh PK
fuente