studio programacion móviles desarrollo curso aplicaciones xml android layout

programacion - findViewById() devuelve nulo para el componente personalizado en el diseño XML, no para otros componentes



findviewbyid null (18)

Asegúrese de que la setContentView(R.layout.main) llame antes de la findViewById(...) ;

Tengo un res/layout/main.xml incluye estos elementos y otros:

<some.package.MyCustomView android:id="@+id/foo" (some other params) /> <TextView android:id="@+id/boring" (some other params) />

En el Activity onCreate, hago esto:

setContentView(R.layout.main); TextView boring = (TextView) findViewById(R.id.boring); // ...find other elements... MyCustomView foo = (MyCustomView) findViewById(R.id.foo); if (foo == null) { Log.d(TAG, "epic fail"); }

Los otros elementos se encuentran con éxito, pero foo vuelve nulo. MyCustomView tiene un constructor MyCustomView(Context c, AttributeSet a) y un Log.d(...) al final de ese constructor aparece con éxito en logcat justo antes del "error épico".

¿Por qué es foo null?


El método findViewById() veces devuelve null cuando la raíz del diseño no tiene ningún atributo android:id . El asistente de Eclipse para generar el archivo xml de diseño no genera automáticamente el atributo android:id para el elemento raíz.


En mi caso, findViewById devolvía nulo porque mi vista personalizada se veía algo así en el XML principal:

<com.gerfmarquez.seekbar.VerticalSeekBar android:id="@+id/verticalSeekBar" android:layout_width="wrap_content" android:layout_height="fill_parent" />

y descubrí que cuando agregué las cosas xmlns funcionó así:

<com.gerfmarquez.seekbar.VerticalSeekBar xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/verticalSeekBar" android:layout_width="wrap_content" android:layout_height="fill_parent" />


En mi caso, la vista estaba en el padre NO en la vista en la que estaba tratando de llamarlo. Así que en la vista infantil tuve que llamar:

RelativeLayout relLayout = (RelativeLayout) this.getParent(); View view1 = relLayout.findViewById(R.id.id_relative_layout_search);


Esto me sucedió con un componente personalizado para Wear, pero es un consejo genérico. Si está utilizando un Stub (como yo estaba usando WatchViewStub ), no puede simplemente poner la llamada a findViewById() cualquier lugar. Todo lo que se encuentra dentro del código debe ser inflado primero, lo que no ocurre después de setContentView() . Por lo tanto, debe escribir algo como esto para esperar que eso suceda:

protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_wear); final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub); stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() { @Override public void onLayoutInflated(WatchViewStub stub) { myCustomViewInst = (MyCustomView) findViewById(R.id.my_custom_view); ...


La opción ''limpia'' funcionó para mí.

En mi caso, la causa principal es que el código fuente reside en un recurso compartido de red, y mi estación de trabajo y servidor de archivos no se sincronizaron correctamente, y se habían desviado en 5 segundos. Las marcas de tiempo en los archivos creados por Eclipse están en el pasado (porque están asignadas por el servidor de archivos) con el reloj de la estación de trabajo, lo que hace que Eclipse resuelva las dependencias entre los archivos generados y de origen incorrectamente. En este caso, un ''clean'' parece funcionar, porque obliga a una reconstrucción completa en lugar de una construcción incremental que depende de marcas de tiempo incorrectas.

Una vez que arreglé la configuración de NTP en mi estación de trabajo, el problema nunca volvió a ocurrir. Sin la configuración adecuada de NTP, sucedería cada pocas horas, ya que los relojes se desplazan rápidamente.


Me encontré con el mismo problema hace un tiempo cuando agregué una Vista personalizada a través del XML de diseño y luego intenté adjuntar una devolución de llamada en otro lugar de la aplicación ...

Creé una vista personalizada y la agregué a mi "layout_main.xml"

public class MUIComponent extends SurfaceView implements SurfaceHolder.Callback { public MUIComponent (Context context, AttributeSet attrs ) { super ( context, attrs ); } // .. }

Y en la Actividad principal, quería adjuntar algunas devoluciones de llamada y obtener referencias de los elementos de la interfaz de usuario del XML.

public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ... MUIInitializer muiInit = new MUIInitializer(); muiInit.setupCallbacks(this); muiInit.intializeFields(this); } }

El iniciador no estaba haciendo nada sofisticado, pero los cambios que intentaba realizar en la vista personalizada (MUIComponent) u otros elementos de UI no personalizados simplemente no aparecían en la aplicación.

public class MUIInitializer { // ... public void setupCallbacks ( Activity mainAct ) { // This does NOT work properly // - The object instance returned is technically an instance of my "MUICompnent" view // but it is a *different* instance than the instance created and shown in the UI screen // - Callbacks never get triggered, changes don''t appear on UI, etc. MUIComponent badInst = (MUIComponent) mainAct.findViewById(R.id.MUIComponent_TESTSURF); // ... // This works properly LayoutInflater inflater = (LayoutInflater) mainAct.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View inflatedLayout = inflater.inflate ( R.layout.activity_main, null ); MUIComponent goodInst = (MUIComponent) inflatedLayout.findViewById(R.id.MUIComponent_TESTSURF); // Add callbacks // ... } }

La diferencia entre "badInst" y "goodInst" es:

  • badInst usa el findViewByID de la actividad
  • GoodInst infla el diseño y usa el diseño inflado para hacer la búsqueda

Mi problema fue un error tipográfico Yo había escrito android.id (punto) en lugar de android:id . :PAG

Aparentemente no hay verificación de sintaxis en mi componente personalizado xml. :(


Mismo problema, pero solución diferente: no llamé

setContentView(R.layout.main)

ANTES de que trate de encontrar la vista como se indica here


Para agregar otro error trivial a las respuestas a tener en cuenta:

Comprueba que estás editando el archivo XML de diseño correcto ...


Para mí, el problema se resolvió cuando agregué la carpeta de res al origen en la ruta de compilación de Java en Configuración del proyecto.


Parece que hay una variedad de razones. Acabo de utilizar "Limpiar ..." en Eclipse para resolver un problema similar. (FindViewByID había funcionado antes y por algún motivo comenzó a devolver nulo).


Porque en el constructor, tuve super(context) lugar de super(context, attrs) .

Tiene sentido, si no pasa los atributos, como el ID, entonces la vista no tendrá una identificación y, por lo tanto, no podrá ser encontrada usando esa identificación. :-)


Si tiene varias versiones de diseño (dependiendo de las densidades de pantalla, versiones de SDK) asegúrese de que todas incluyan el elemento que está buscando.


Tenía el mismo problema.

Tenía un diseño con pocos niños. Desde el constructor de uno de ellos estaba tratando de obtener referencia (mediante context.findViewById) a otro niño. No estaba funcionando porque el segundo hijo se definió más en el diseño.

Lo he resuelto así:

setContentView(R.layout.main); MyView first = findViewById(R.layout.first_child); first.setSecondView(findViewById(R.layout.second_child));

Funcionaría también si el orden de los niños fuera opuesto, pero supongo que generalmente debería hacerse como se indicó anteriormente.


Tengo el mismo problema porque en mi vista personalizada anulé el constructor pero invoqué el super contructor sin el parámetro attrs. Eso es copiar y pegar

Mi versión previa del constructor:

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

Ahora tengo:

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

¡Y eso funciona!


Tuve el mismo problema porque olvidé actualizar la identificación de la vista en todas mis carpetas de diseño.


Yo tuve el mismo problema. Mi error fue eso: escribí

LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); View layout=inflater.inflate(R.layout.dlg_show_info, null); alertDlgShowInfo.setView(layout); TableRow trowDesc=(TableRow)findViewById(R.id.trowDesc);

y como utilicé un inflador para "cargar" la vista desde un archivo XML, la última línea era incorrecta. Para resolverlo, tuve que escribir:

TableRow trowDesc=(TableRow)layout.findViewById(R.id.trowDesc);

Escribí mi solución, en caso de que alguien tenga el mismo problema.