Uso de Core Animation para modificar el contenido de una vista
Uno de los frameworks que han hecho su debut con Leopard ha sido Core Animation.
Según Apple, Core Animation es un framework para renderizado gráfico, proyección y animación. Lo que, traducido, quiere decir, que es un framework que facilita enormemente la animación de elementos de interfaz.
Por ejemplo, es muy sencillo cambiar en tiempo de ejecución el contenido de una vista, sustituyéndolo por otra vista completamente distinta, presentando el cambio con una animación discreta, pero efectiva para reforzar el feedback que recibe el usuario del proceso.
En este ejemplo vamos a partir de este primer estado:
Para llegar a este otro:
Como puede verse, en este caso el cambio no es muy grande, se pasa de un slider a un desplegable, no obstante, la transición se hará utilizando la animación por defecto del framework (dissolve).
Construir el interfaz de la aplicación es sencillo. En la ventana principal de la misma, voy a colocar un botón, que será el que lance la animación, y una instancia de NSView, cuyo contenido iré modificando en tiempo de ejecución. Éste sería el aspecto de mi ventana:
Además, construyo dos instancias más de NSView:
Como se puede ver, el ancho de las dos vistas es diferente.
Construyo también el esqueleto del controlador de la aplicación. Tendré tres outlets, uno a cada uno de las tres vistas (la de la ventana principal, y las dos vistas independientes). Además, tendré un action para el botón de "swap" y un booleano que me indicará si la vista que se está mostrando en cada instante es la primera o la segunda:
#import
@interface ViewSwapController : NSObject
{
IBOutlet NSView *containerView;
IBOutlet NSView *firstView;
IBOutlet NSView *secondView;
BOOL showFirst;
}
-(IBAction) swapView: (id) sender;
@end
Tras crear la instancia de NSObject en Interface Builder y asignarle como clase mi controlador, la estructura del nib sería como la siguiente:
Quiero que mi controlador haga lo siguiente: al arrancar la aplicación, insertará dentro de la vista de la ventana principal la primera de las dos vistas independientes que he creado, y cuando se haga clic en el botón de "swap" se cambiará esa vista por la segunda.
Por tanto, el método awakeFromNib será:
-(void) awakeFromNib
{
showFirst = NO;
[ containerView setWantsLayer: YES ];
[ [ containerView animator ] addSubview: firstView ];
}
Simplemente, preparo la vista de la ventana principal para que sea animable, y le añado como subvista la primera de mis vistas personalizadas.
Al hacer clic en el botón:
-(IBAction) swapView: (id) sender
{
NSRect containerFrame = [ containerView frame ];
NSRect firstViewFrame;
NSNumber *newCoord;
NSView *tempFirst;
NSView *tempSecond;
if( showFirst )
{
tempFirst = secondView;
tempSecond = firstView;
showFirst = NO;
}
else
{
tempFirst = firstView;
tempSecond = secondView;
showFirst = YES;
}
[ [ containerView animator ] replaceSubview: tempFirst with: tempSecond ];
firstViewFrame = [ tempSecond frame ];
newCoord = [ NSNumber numberWithFloat: containerFrame.size.width /2 - firstViewFrame.size.width/2 ];
[ tempSecond setFrameOrigin: NSMakePoint( [ newCoord intValue ] , 0 ) ];
}
En primer lugar, calculo el ancho de la vista contenedor, y de la vista que quiero colocar dentro de la misma, para luego poder centrarla, y posteriormente reemplazo la vista que esté dentro del contenedor por la que corresponda.
Lo importante, lo que hace que la transición entre las dos vistas sea animada, es que no ataco directamente la vista contenedor para modificar su contenido, sino que utilizo el decorator que crea CoreAnimation (que se llama animator) para que, de esa forma, cualquier modificación de las propiedades de esa vista se muestre de forma animada.
El proyecto puede descargarse del repositorio público de subversion:
svn co http://svn.liadorasoft.com/viewswap ViewSwap
Enlaces relacionados:
Un clon de Photo Booth en 32 minutos
Extensión por delegación
Bindings, NSArrayController y Value Transformers