¿Cuándo se llama layoutSubviews?
Tengo una vista personalizada que no recibe layoutSubview
mensajes durante la animación.
Tengo una vista que llena la pantalla. Tiene una vista secundaria personalizada en la parte inferior de la pantalla que cambia el tamaño correctamente en Interface Builder si cambio la altura de la barra de navegación. layoutSubviews
se llama cuando se crea la vista, pero nunca más. Mis subviews están correctamente establecidos. Si desactivo la barra de estado de la llamada, el subview layoutSubviews
no se llama en absoluto, a pesar de que la vista principal anima su redimensionar.
¿Bajo qué circunstancias se llama layoutSubviews
realmente?
Tengo autoresizesSubviews
establecido en NO
para mi vista personalizada. Y en Interface Builder tengo los puntales superior e inferior y el conjunto de flechas verticales.
10 answers
Tenía una pregunta similar, pero no estaba satisfecho con la respuesta (o cualquiera que pudiera encontrar en la red), así que lo intenté en la práctica y esto es lo que obtuve:
-
init
no causa quelayoutSubviews
ser llamado (duh) -
addSubview:
causaslayoutSubviews
para ser llamado a la punto de vista agregado, la vista se añadido a (vista de destino), y todos los subviews of the target - ver
setFrame
llama inteligentementelayoutSubviews
en la vista que tiene su marco establecido solamente si el parámetro tamaño del marco ser diferente - desplazando un UIScrollView
causas
layoutSubviews
para ser llamado el ScrollView, y su superview - rotar un dispositivo solo llama
layoutSubview
en la vista padre (el responding ViewController primary vista) - Cambiar el tamaño de una vista llamará a
layoutSubviews
en su supervisión
Mis resultados - http://blog.logichigh.com/2011/03/16/when-does-layoutsubviews-get-called/
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-03 09:07:17
Basándome en la respuesta anterior de @BadPirate, experimenté un poco más y se me ocurrieron algunas aclaraciones/correcciones. Encontré que layoutSubviews:
será llamado en una vista si y solo si:
- Sus propios límites (no marco) cambiado.
- Los límites de una de sus subviews directas cambiaron.
- Se agrega una subvista a la vista o se elimina de la vista.
Algunos detalles relevantes:
- Los límites se consideran cambiados solo si el nuevo el valor es diferente, incluyendo un origen diferente. Tenga en cuenta específicamente que es por eso que
layoutSubviews:
se llama cada vez que un desplazamiento de UIScrollView, ya que realiza el desplazamiento cambiando el origen de sus límites. - Cambiar el marco solo cambiará los límites si el tamaño ha cambiado, ya que esto es lo único que se propaga a la propiedad bounds.
- Un cambio en los límites de una vista que aún no está en una jerarquía de vista resultará en una llamada a
layoutSubviews:
cuando la vista se agrega finalmente a un ver jerarquía . - Y solo para completar: estos disparadores no llaman directamente a layoutSubviews, sino que llaman
setNeedsLayout
, lo que establece/eleva una bandera. Cada iteración del bucle de ejecución, para todas las vistas en la jerarquía de vistas, este indicador está marcado. Para cada vista en la que se encuentra el indicador elevado, se llama alayoutSubviews:
y se restablece el indicador. Las vistas superiores a la jerarquía serán verificadas / llamadas primero.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-06 01:07:48
Los cambios de diseño pueden ocurrir siempre que ocurra cualquiera de los siguientes eventos en un punto de vista:
A. El tamaño del rectángulo de límites de una vista cambia.
b. Se produce un cambio de orientación de la interfaz, que generalmente desencadena un cambio en el rectángulo de límites de la vista raíz.
c. The el conjunto de subcapas principales de animación asociadas con la capa de la vista cambia y requiere diseño.
d. Su aplicación obliga a que se produzca el layout llamando al métodosetNeedsLayout
olayoutIfNeeded
de una vista.
e. Su aplicación fuerza el layout llamando al métodosetNeedsLayout
del objeto de capa subyacente de la vista.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-16 02:09:09
Algunos de los puntos en La respuesta de BadPirate son solo parcialmente ciertos:
-
Para
addSubView
puntoaddSubview
hace que layoutSubviews se invoque en la vista que se agrega, en la vista a la que se agrega (vista de destino) y en todas las subviews del destino.Depende de la máscara de autoresize de la vista (vista de destino). Si tiene la máscara autoresize ACTIVADA, layoutSubview será llamada en cada
addSubview
. Si no tiene máscara de tamaño automático, entonces layoutSubview será se llama solo cuando cambia el tamaño del marco de la vista (vista de destino).Ejemplo: si ha creado UIView programáticamente (no tiene máscara de autoresize por defecto), layoutSubview solo se llamará cuando el marco UIView cambie, no en cada
addSubview
.Es a través de esta técnica que el rendimiento de la aplicación también aumenta.
-
Para el punto de rotación del dispositivo
Rotar un dispositivo solo llama a layoutSubview en la vista padre (la respuesta Vista primaria de ViewController)
Esto puede ser cierto solo cuando su VC está en la jerarquía de VC (raíz en
window.rootViewController
), bueno, este es el caso más común. En iOS 5, si crea un VC, pero no se agrega a ningún otro VC, este VC no se notará cuando el dispositivo gire. Por lo tanto, su vista no se notaría llamando a layoutSubviews.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:45
Llamando
[self.view setNeedsLayout];
en ViewController hace que llame a viewDidLayoutSubviews
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-14 20:39:58
Rastreé la solución hasta la insistencia de Interface Builder de que los resortes no se pueden cambiar en una vista que tiene los elementos de pantalla simulados activados (barra de estado, etc.).). Dado que los resortes estaban apagados para la vista principal, esa vista no podía cambiar de tamaño y, por lo tanto, se desplazó hacia abajo en su totalidad cuando apareció la barra de llamada.
Desactivar las características simuladas, luego cambiar el tamaño de la vista y configurar los resortes correctamente causó que la animación se produjera y mi método se called.
Un problema adicional en la depuración es que el simulador sale de la aplicación cuando el estado de la llamada está activado a través del menú. Salir de app = sin depurador.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-09 14:41:40
¿Has mirado la disposición necesaria?
El fragmento de documentación se encuentra a continuación. ¿Funciona la animación si llamas a este método explícitamente durante la animación?
Layout necesario Establece las subviews si es necesario.
- (void)layoutIfNeeded
Discusión Utilice este método para forzar el diseño de subviews antes de dibujar.
Disponibilidad Disponible en iPhone OS 2.0 y versiones posteriores.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-08 04:12:24
Al migrar una aplicación OpenGL desde SDK 3 a 4, layoutSubviews ya no se llamaba. Después de mucho ensayo y error, finalmente abrí MainWindow.xib, seleccionó el objeto Window, en el inspector eligió la pestaña Window Attributes (leftmost) y marcó "Visible at launch". Parece que en SDK 3 todavía se utiliza para causar una llamada layoutSubviews, pero no en 4.
6 horas de frustración acabadas.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-06-24 07:13:42
Otra parte del rompecabezas es que la ventana debe hacerse clave:
[window makeKeyAndVisible];
De lo contrario, las subviews no se redimensionan automáticamente.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-30 06:08:57
Un caso bastante oscuro, pero potencialmente importante cuando layoutSubviews
nunca se llama es:
import UIKit
class View: UIView {
override class var layerClass: AnyClass { return Layer.self }
class Layer: CALayer {
override func layoutSublayers() {
// if we don't call super.layoutSublayers()...
print(type(of: self), #function)
}
}
override func layoutSubviews() {
// ... this method never gets called by the OS!
print(type(of: self), #function)
}
}
let view = View(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-02 14:48:08