Tengo una capa con un código de dibujo complejo en su método -drawInContext:. Estoy tratando de minimizar la cantidad de dibujo que necesito hacer, así que estoy usando -setNeedsDisplayInRect: para actualizar solo las partes cambiadas. Esto está funcionando espléndidamente. Sin embargo, cuando el sistema gráfico actualiza mi capa, está pasando de la imagen antigua a la nueva usando un fundido cruzado. Me gustaría que cambiara al instante.
Intenté usar CATransaction para desactivar las acciones y establecer la duración en cero, y tampoco funciona. Aquí está el código que estoy usando:
[CATransaction begin];
[CATransaction setDisableActions: YES];
[self setNeedsDisplayInRect: rect];
[CATransaction commit];
¿Hay un método diferente en CATransaction que debería usar en su lugar (también probé -setValue: forKey: with kCATransactionDisableActions, mismo resultado).
iphone
ios
core-animation
calayer
Ben Gottlieb
fuente
fuente
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ });
Respuestas:
Puede hacer esto configurando el diccionario de acciones en la capa para que regrese
[NSNull null]
como una animación para la clave adecuada. Por ejemplo, yo usopara deshabilitar las animaciones de fundido de entrada / salida al insertar o cambiar las subcapas dentro de una de mis capas, así como los cambios en el tamaño y el contenido de la capa. Creo que la
contents
clave es la que está buscando para evitar el fundido cruzado en el dibujo actualizado.Versión rápida:
fuente
@"position"
tecla.@"hidden"
propiedad en el diccionario de acción si está alternando la visibilidad de una capa de esa manera y desea deshabilitar la animación de opacidad.actionForKey:
su lugar), el descubrimientofontSize
,contents
,onLayout
ybounds
. Parece que puede especificar cualquier clave que pueda usar en elsetValue:forKey:
método, en realidad especificando rutas de teclas complejas comobounds.size
.También:
fuente
//foo
con[self setNeedsDisplayInRect: rect]; [self displayIfNeeded];
para responder la pregunta original.[CATransaction setDisableActions:YES]
[CATransaction setDisableActions:YES]
es una abreviatura de solo la[CATransaction setValue:forKey:]
línea. Todavía necesitas elbegin
commit
líneas y .Cuando cambia la propiedad de una capa, CA generalmente crea un objeto de transacción implícito para animar el cambio. Si no desea animar el cambio, puede deshabilitar las animaciones implícitas creando una transacción explícita y estableciendo su propiedad kCATransactionDisableActions en true .
C objetivo
Rápido
fuente
Además de la respuesta de Brad Larson : para capas personalizadas (creadas por usted) puede usar la delegación lugar de modificar el
actions
diccionario de la capa . Este enfoque es más dinámico y puede ser más eficaz. Y permite deshabilitar todas las animaciones implícitas sin tener que enumerar todas las teclas animables.Desafortunadamente, es imposible usar
UIView
s como delegados de capa personalizados, porque cada unoUIView
ya es un delegado de su propia capa. Pero puede usar una clase auxiliar simple como esta:Uso (dentro de la vista):
A veces es conveniente tener el controlador de vista como delegado para las subcapas personalizadas de vista; en este caso no hay necesidad de una clase auxiliar, puede implementar el
actionForLayer:forKey:
método directamente dentro del controlador.Nota importante: no intente modificar el delegado de
UIView
la capa subyacente (por ejemplo, para habilitar animaciones implícitas), sucederán cosas malas :)Nota: si desea animar (no deshabilitar la animación para) los redibujos de capa, es inútil poner la
[CALayer setNeedsDisplayInRect:]
llamada dentro de unCATransaction
, porque el redibujo real puede (y probablemente) ocurrirá a veces más tarde. El buen enfoque es usar propiedades personalizadas, como se describe en esta respuesta .fuente
CALayer
evitar quenoImplicitAnimations
funcionara. ¿Quizás debería marcar su propia respuesta como correcta y explicar qué estaba mal con esa capa?CALayer
instancia incorrecta (tenía dos en ese momento).NSNull
no implementa elCAAction
protocolo y este no es un protocolo que solo tenga métodos opcionales. Este código también falla y ni siquiera puedes traducirlo a rápido. Mejor solución: haga que su objeto se ajuste alCAAction
protocolo (con unrunActionForKey:object:arguments:
método vacío que no hace nada) y regrese enself
lugar de[NSNull null]
. El mismo efecto pero seguro (no se bloqueará con seguridad) y también funciona en Swift.Aquí hay una solución más eficiente, similar a la respuesta aceptada pero para Swift . En algunos casos, será mejor que crear una transacción cada vez que modifique el valor, lo cual es un problema de rendimiento como otros han mencionado, por ejemplo, el caso de uso común de arrastrar la posición de la capa a 60 fps.
Consulte los documentos de Apple para ver cómo se resuelven las acciones de capa . La implementación del delegado omitiría un nivel más en la cascada, pero en mi caso eso fue demasiado complicado debido a la advertencia de que el delegado necesita estar configurado en la UIView asociada .
Editar: actualizado gracias al comentador que señala que se
NSNull
ajusta aCAAction
.fuente
NullAction
para Swift, ya seNSNull
ajusta paraCAAction
que pueda hacer lo mismo que hace en el objetivo C: layer.actions = ["position": NSNull ()]Según la respuesta de Sam y las dificultades de Simon ... agregue la referencia de delegado después de crear CSShapeLayer:
... en otra parte del archivo "m" ...
Esencialmente lo mismo que Sam sin la capacidad de alternar a través de la disposición variable personalizada "disableImplicitAnimations". Más de un enfoque de "cable duro".
fuente
En realidad, no encontré ninguna de las respuestas correctas. El método que resolvió el problema para mí fue este:
Luego puede usar la lógica que contenga, para deshabilitar una animación específica, pero como quería eliminarlos a todos, regresé nulo.
fuente
Para deshabilitar animaciones de capa implícitas en Swift
fuente
disableActions()
ya que parece que hace lo mismo, pero en realidad es para obtener el valor actual. Creo que también está marcado@discardable
, lo que hace que sea más difícil de detectar. Fuente: developer.apple.com/documentation/quartzcore/catransaction/…Encontró un método más simple para deshabilitar la acción dentro de un
CATransaction
que internamente solicitasetValue:forKey:
lakCATransactionDisableActions
clave:Rápido:
fuente
Agregue esto a su clase personalizada donde está implementando el método -drawRect (). Realice cambios en el código para satisfacer sus necesidades, para mí 'opacidad' hizo el truco para detener la animación de fundido cruzado.
fuente
Si alguna vez necesita una solución muy rápida (pero ciertamente hacky), puede valer la pena hacerlo (Swift):
fuente
view.layer?.actions = [:]
realmente no funcione. Establecer la velocidad es feo pero funciona.Actualizado para acelerar e inhabilitar solo una animación de propiedad implícita en iOS, no en MacOS
Otro ejemplo, en este caso eliminando dos animaciones implícitas.
fuente
A partir de iOS 7, hay un método de conveniencia que hace exactamente esto:
fuente
Para deshabilitar la animación molesta (borrosa) al cambiar la propiedad de cadena de un CATextLayer, puede hacer esto:
y luego úselo así (no olvide configurar su CATextLayer correctamente, por ejemplo, la fuente correcta, etc.):
Puedes ver mi configuración completa de CATextLayer aquí:
Ahora puede actualizar caTextLayer.string tanto como desee =)
Inspirado por esto y esta respuesta.
fuente
Prueba esto.
Advertencia
Si configura un delegado de la instancia de UITableView, a veces puede ocurrir un bloqueo (probablemente el hittest de scrollview se llama recursivamente).
fuente