¿Cómo puedes saber cuándo se ha dibujado un diseño?

Tengo una vista personalizada que dibuja un bitmap desplazable a la pantalla. Para inicializarlo, necesito pasar el tamaño en píxeles del objeto de diseño principal. Pero durante las funciones onCreate y onResume, el diseño aún no se ha dibujado, por lo que layout.getMeasuredHeight () devuelve 0.

Como solución, agregué un controlador para esperar un segundo y luego medir. Esto funciona, pero es descuidado, y no tengo idea de cuánto puedo recortar el tiempo antes de terminar antes de que se dibuje el diseño.

Lo que quiero saber es, ¿cómo puedo detectar cuándo se dibuja un diseño? ¿Hay un evento o callback?

Puede agregar un observador de árbol al diseño. Esto debería devolver el ancho y la altura correctos. onCreate() antes de que se realice el diseño de las vistas secundarias. Por lo tanto, el ancho y la altura aún no se calculan. Para obtener el alto y el ancho, ponlo en el método onCreate() :

 final LinearLayout layout = (LinearLayout) findViewById(R.id.YOUR_VIEW_ID); ViewTreeObserver vto = layout.getViewTreeObserver(); vto.addOnGlobalLayoutListener (new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { layout.getViewTreeObserver().removeOnGlobalLayoutListener(this); int width = layout.getMeasuredWidth(); int height = layout.getMeasuredHeight(); } }); 

Una forma realmente fácil es simplemente llamar a post() en su diseño. Esto ejecutará su código el siguiente paso, después de que su vista ya haya sido creada.

 YOUR_LAYOUT.post( new Runnable() { @Override public void run() { int width = YOUR_LAYOUT.getMeasuredWidth(); int height = YOUR_LAYOUT.getMeasuredHeight(); } }); 

Para evitar el código desaprobado y las advertencias, puede usar:

 view.getViewTreeObserver().addOnGlobalLayoutListener( new ViewTreeObserver.OnGlobalLayoutListener() { @SuppressWarnings("deprecation") @Override public void onGlobalLayout() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { view.getViewTreeObserver() .removeOnGlobalLayoutListener(this); } else { view.getViewTreeObserver() .removeGlobalOnLayoutListener(this); } yourFunctionHere(); } }); 

Otra respuesta es:
Intente verificar las dimensiones de la vista en onWindowFocusChanged .

Cuando se llama onMeasure la vista obtiene su ancho / alto medido. Después de esto, puede llamar a layout.getMeasuredHeight() .

Desafortunadamente, ninguna de estas soluciones funcionó para mí de manera confiable. Entonces, esto es lo que encontré funcionó para mí y espero que funcione para otros.

La idea clave es que OnPreDrawListener se llama muchas veces y no hay garantía de que la primera, segunda, tercera, etc. será la iteración en la que su vista tenga un ancho o alto medidos válidos.

Por lo tanto, no deje de interrogar esa vista hasta que le haya proporcionado una respuesta razonable ( view.getMeasuredWidth() <= 0 ). También podría establecer un límite para la cantidad de veces que verifica un measuredWidth mayor que cero en caso de que nunca se dibuje su vista, aunque esto podría indicar otros problemas con su código.

 ViewTreeObserver viewTreeObserver = view.getViewTreeObserver(); viewTreeObserver.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { if (view.getMeasuredWidth() <= 0) { return false; } view.getViewTreeObserver().removeOnPreDrawListener(this); int width = view.getMeasuredWidth(); int height = view.getMeasuredHeight(); //Do something with width and height here! return true; } });