¿Cómo puedo animar tintColor a gris en un control personalizado cuando se muestra una hoja/alerta en iOS 7?
iphone ios7 (3)
En iOS 7, cuando se presenta una UIActionSheet
, el sistema controla todo animando su tintColor
a gris. Cuando se descarta la hoja, se animan hacia atrás.
Tengo algunos controles con imágenes de fondo personalizadas o implementaciones drawRect
que usan el color del tinte, y me gustaría que animen ese cambio al igual que los controles del sistema.
Apple agregó - (void)tintColorDidChange
a UIView
, pero volver a dibujar con el nuevo color en este método no anima el cambio; simplemente cambia de color completo a gris completo inmediatamente, lo que se ve mal cuando otros controles del sistema están animando.
¿Cómo puedo hacer que mis controles personalizados animen la transición de tintColor
como la de Apple?
¿Has probado tintAdjustmentMode
?
Debería ver WWDC 2013 Session 214 Personalizar la apariencia de su aplicación para iOS 7 y leer la aplicación de demostración TicTacToe
Algo como esto
- (void)onPopupOpened
{
[UIView animateWithDuration:0.3 animations:^{
window.tintAdjustmentMode = UIViewTintAdjustmentModeDimmed;
}];
popupView.tintAdjustmentMode = UIViewTintAdjustmentModeNormal;
popupView.tintColor = [UIColor redColor];
}
- (void)onPopupClosed
{
[UIView animateWithDuration:0.3 animations:^{
window.tintAdjustmentMode = UIViewTintAdjustmentModeAutomatic;
}];
}
¿No debería drawRect:
llamarse automáticamente para que la animación se actualice para el nuevo tintColor
?
He hecho una aplicación de demostración que tiene tres controles en el controlador de vista principal. El primero es un botón que muestra una hoja de acción estándar. El segundo es un botón que está ahí para observación (el botón tocado es difícil de comparar durante la animación). La tercera es una subclase UIView
personalizada que simplemente dibuja un rectángulo del tintColor
de la vista. Cuando se llama a setNeedsDisplay
, setNeedsDisplay
, que a su vez llamará a drawRect:
Creé una nueva aplicación con un controlador de vista:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[[UIApplication sharedApplication] keyWindow].tintColor = [UIColor blueColor];
// Button to bring up action sheet
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = (CGRect){10,30,300,44};
[button setTitle:@"Present Action Sheet" forState:UIControlStateNormal];
[button addTarget:self
action:@selector(didTapPresentActionSheetButton:)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
// Another button for demonstration
UIButton *anotherButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
anotherButton.frame = (CGRect){10,90,300,44};
[anotherButton setTitle:@"Another Button" forState:UIControlStateNormal];
[self.view addSubview:anotherButton];
// Custom view with tintColor
TESTCustomView *customView = [[TESTCustomView alloc] initWithFrame:(CGRect){10,150,300,44}];
[self.view addSubview:customView];
}
- (void)didTapPresentActionSheetButton:(id)sender
{
UIActionSheet *as = [[UIActionSheet alloc] initWithTitle:@"Action Sheet"
delegate:nil
cancelButtonTitle:@"Cancel"
destructiveButtonTitle:@"Delete"
otherButtonTitles:@"Other", nil];
[as showInView:self.view];
}
donde TESTCustomView
es una subclase UIView
con implementación de la siguiente manera:
- (void)drawRect:(CGRect)rect
{
NSLog(@"Drawing with tintColor: %@", self.tintColor);
// Drawing code
[super drawRect:rect];
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(c, self.tintColor.CGColor);
CGContextFillRect(c, rect);
}
- (void)tintColorDidChange
{
[self setNeedsDisplay];
}
La ejecución de esta aplicación en el simulador muestra que tintColor de la vista personalizada se anima automáticamente con las instancias de UIButton
estándar en el controlador de vista.
Puede hacer esto con una transición de Core Animation aplicada a la capa de vista:
//set up transition
CATransition *transition = [CATransition animation];
transition.type = kCATransitionFade;
transition.duration = 0.4;
[self.layer addAnimation:transition forKey:nil];
//now trigger a redraw of the background using the new colour
//and the transition will cover the redraw with a crossfade
self.flagToIndicateColorShouldChange = YES;
[self setNeedsDisplay];
EDITAR: puede haber una condición de carrera entre la animación y el rediseño dependiendo de cómo se realiza el redibujado. Si puede publicar el código de redibujado original que intentó actualizar inmediatamente (sin animación) puedo proporcionar una respuesta más específica.