2011-05-19 10 views
7

Estoy tratando de deslizar en un NSView usando animación central. Creo que necesito usar animación explícita en lugar de confiar en algo como [[view animator] setFrame:newFrame]. Esto se debe principalmente a que necesito configurar el delegado de animación para que actúe después de que la animación haya finalizado.Animación explícita de NSView usando animación central

Lo tengo funcionando bien usando el animador, pero como dije, necesito que me avisen cuando termine la animación. Mi código es actualmente como:

// Animate the controlView 
NSRect viewRect = [controlView frame]; 
NSPoint startingPoint = viewRect.origin; 
NSPoint endingPoint = startingPoint; 
endingPoint.x += viewRect.size.width; 
[[controlView layer] setPosition:NSPointToCGPoint(endingPoint)]; 

CABasicAnimation *controlPosAnim = [CABasicAnimation animationWithKeyPath:@"position"]; 
[controlPosAnim setFromValue:[NSValue valueWithPoint:startingPoint]]; 
[controlPosAnim setToValue:[NSValue valueWithPoint:endingPoint]]; 
[controlPosAnim setDelegate:self]; 
[[controlView layer] addAnimation:controlPosAnim forKey:@"controlViewPosition"]; 

Esto funciona visualmente (y me notifican al final) pero parece que la ControlView real no consigue mover. Si hago que la ventana se actualice, el controlView desaparece. He intentado reemplazar

[[controlView layer] setPosition:NSPointToCGPoint(endingPoint)]; 

con

[controlView setFrame:newFrame]; 

y que tenga como consecuencia la vista (y capa) para moverse, pero es algo corromper de tal manera que mi aplicación muere con una falla seg poco después.

La mayoría de los ejemplos de animación explícita parecen moverse solo a CALayer. Debe haber una forma de mover el NSView y también poder establecer un delegado. Cualquier ayuda sería apreciada.

Respuesta

5

Creo que debe llamar al setPosition al final (después de configurar la animación). Además, no creo que deba animar explícitamente la capa de la vista, sino la vista en sí misma usando el animador y configurando las animaciones. Puede utilizar delegados también con el animador :)

// create controlPosAnim 
[controlView setAnimations:[NSDictionary dictionaryWithObjectsAndKeys:controlPosAnim, @"frameOrigin", nil]]; 
[[controlView animator] setFrame:newFrame]; 
+0

Gracias por la respuesta. Logré que esto funcionara con una pequeña reorganización del código. Creo que los ejemplos de Apple durante WWDC te dijeron que manipules la vista * antes * de configurar la animación. Entonces, ¿cómo puedes usar delegados con animator? He buscado por todas partes ejemplos de eso y salió vacío. También vi numerosos mensajes que decían que no era posible. – btschumy

+0

Establezca el delegado en su controlPosAnim, agréguelo a las animaciones de controlView, se invocarán los métodos de delegado. –

+0

OK gracias por la información – btschumy

8

Los cambios realizados en vistas entran en vigor al final del bucle de ejecución actual. Lo mismo aplica para cualquier animación aplicada a capas.

Si anima la capa de una vista, la vista en sí misma no se ve afectada, por lo que la vista parece volver a su posición original cuando finaliza la animación.

Con estas dos cosas en mente, puede obtener el efecto que desea configurando el marco de la vista a lo que desea que sea cuando la animación finalice y luego agregue una animación explícita a la capa de la vista.

Cuando comienza la animación, mueve la vista a la posición de inicio, la anima a la posición final y cuando termina la animación, la vista tiene el marco que ha especificado.

- (IBAction)animateTheView:(id)sender 
{ 
    // Calculate start and end points. 
    NSPoint startPoint = theView.frame.origin; 
    NSPoint endPoint = <Some other point>;  

    // We can set the frame here because the changes we make aren't actually 
    // visible until this pass through the run loop is done. 
    // Furthermore, this change to the view's frame won't be visible until 
    // after the animation below is finished. 
    NSRect frame = theView.frame; 
    frame.origin = endPoint; 
    theView.frame = frame; 

    // Add explicit animation from start point to end point. 
    // Again, the animation doesn't start immediately. It starts when this 
    // pass through the run loop is done. 
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"]; 
    [animation setFromValue:[NSValue valueWithPoint:startPoint]]; 
    [animation setToValue:[NSValue valueWithPoint:endPoint]]; 
    // Set any other properties you want, such as the delegate. 
    [theView.layer addAnimation:animation forKey:@"position"]; 
} 

Por supuesto, para que este código funcione, debe asegurarse de que tanto su vista como su super visión tengan capas. Si la supervista no tiene una capa, obtendrá gráficos dañados.

+0

Wow gracias por el último comentario sobre las capas super e infantil que necesitan o si no obtendrás gráficos dañados. Esto me ayudó a solucionar un problema completamente diferente. ¡Gracias! – migs647

Cuestiones relacionadas