UIViewController - problema com a transição de dispensa personalizada
Eu tenho um UIViewController de conteúdo que apresenta um UIViewController de configurações usando uma transição personalizada. A apresentação é compresentViewController:animated:completion:
.
Mais tarde, quando descartar as configurações comdismissViewControllerAnimated:completion:
, o controlador de apresentação é repentinamente retornado à sua posição inicial antes da apresentação do controlador de configurações.
Eu tenho uma solução alternativa para isso no dispositivo, mas não no simulador. No entanto, eu gostaria de saber o que estou fazendo de errado, em vez de invadir uma loja que a faz desaparecer. Também pretendo tornar essa animação interativa e suspeito que esses problemas serão ampliados quando eu fizer isso.
Transição personalizada - Abrindo o capôO efeito desejado é que oapresentando o controlador desliza para baixo na tela e oapresentado O controlador é visto atrás dele, de onde levanta para preencher a tela. A parte superior do controlador de apresentação permanece na tela durante a vida útil do uso do controlador apresentado. Ele fica na parte inferior da tela, masacima o controlador apresentado.
Você pode imaginar levantando o capô de um carro (o controlador de apresentação frontal) para ver o motor por trás (as configurações apresentadas), mas o capô permanece visível na parte inferior por um pouco de contexto.
Pretendo refinar isso para que o controlador de apresentação pareça realmente elevar a perspectiva de uma maneira 3D, mas ainda não cheguei tão longe.
Quando as configurações são descartadas, o controlador de apresentação original (castelo) deve deslizar para cima na tela e o controlador apresentado (configurações) afunda um pouco (fechando o castelo).
CódigoAqui está o método que ativa e desativa as configurações da tela (é chamado apenas por um UIButton). Você notará que o controlador de exibição de apresentação se configura como o<UIViewControllerTransitioningDelegate>
.
-(void) toggleSettingsViewController
{
const BOOL settingsAreShowing = [self presentedViewController] != nil;
if(!settingsAreShowing)
{
UIViewController *const settingsController = [[self storyboard] instantiateViewControllerWithIdentifier: @"STSettingsViewController"];
[settingsController setTransitioningDelegate: self];
[settingsController setModalPresentationStyle: UIModalPresentationCustom];
[self presentViewController: settingsController animated: YES completion: nil];
}
else
{
[self dismissViewControllerAnimated: YES completion: nil];
}
}
Implementar<UIViewControllerAnimatedTransitioning>
o controlador de exibição de apresentação também apenas retorna como o<UIViewControllerAnimatedTransitioning>
-(id<UIViewControllerAnimatedTransitioning>) animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
return self;
}
-(id<UIViewControllerAnimatedTransitioning>) animationControllerForDismissedController:(UIViewController *)dismissed
{
// Test Point 1.
return self;
}
Então, finalmente, o controlador de exibição de apresentação receberáanimateTransition:
:
-(void) animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
UIViewController *const fromController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *const toController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
const BOOL isUnwinding = [toController presentedViewController] == fromController;
const BOOL isPresenting = !isUnwinding;
UIViewController * presentingController = isPresenting ? fromController : toController;
UIViewController * presentedController = isPresenting ? toController : fromController;
if(isPresenting)
{
// Add the presented controller (settings) to the view hierarchy _behind_ the presenting controller.
[[transitionContext containerView] insertSubview: [presentedController view] belowSubview: [presentingController view]];
// Set up the initial position of the presented settings controller. Scale it down so it seems in the distance. Alpha it down so it is dark and shadowed.
presentedController.view.transform = CGAffineTransformMakeScale(0.9, 0.9);
presentedController.view.alpha = 0.7;
[UIView animateWithDuration: [self transitionDuration: transitionContext] animations:^{
// Lift up the presented controller.
presentedController.view.transform = CGAffineTransformMakeScale(1.0, 1.0);
// Brighten the presented controller (out of shadow).
presentedController.view.alpha = 1;
// Push the presenting controller down the screen – 3d effect to be added later.
presentingController.view.layer.transform = CATransform3DMakeTranslation(0,400,0);
} completion: ^(BOOL finished){
[transitionContext completeTransition: ![transitionContext transitionWasCancelled]];
}];
}
else
{
// Test Point 2.
// !!!This line should not be needed!!!
// It resets the presenting controller to where it ought to be anyway.
presentingController.view.layer.transform = CATransform3DMakeTranslation(0,400,0);
[UIView animateWithDuration: [self transitionDuration: transitionContext] animations:^{
// Bring the presenting controller back to its original position.
presentingController.view.layer.transform = CATransform3DIdentity;
// Lower the presented controller again and put it back in to shade.
presentedController.view.transform = CGAffineTransformMakeScale(0.9, 0.9);
presentedController.view.alpha = 0.4;
} completion:^(BOOL finished) {
[transitionContext completeTransition: ![transitionContext transitionWasCancelled]];
}];
}
}
-(NSTimeInterval) transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
{
return 0.5;
}
ProblemaNo código acima, eu indiquei!!! Esta linha não deve ser necessária !!!.
O que está acontecendo é que entrePonto de teste 1 ePonto de teste 2 a posição da tela do controlador de exibição de apresentação é redefinida para ser os limites de tela cheia padrão. Então, em vez de estar na parte inferior da tela pronta para animar novamente sem problemas, ela subitamente salta a tela para a posição de que também deve animar!
Eu tentei várias abordagens para animar o controlador de exibição de apresentação na tela:
Eu mudei o quadro de vista.Eu mudei a transformação de sua visão.Alterei a transformação 3d da camada da visualização.Em todos os casos, emPonto de teste 1, quando o delegado de transição é solicitado, o controlador de apresentação é configurado como eu esperaria. No entanto, em todos os casos, emPonto de teste 2, o controlador de exibição de apresentação perdeu a posição correta e foi "limpo" para ter a posição normal de tela cheia na qual desejo animar.
No trabalho acima, mudei explicitamente o controlador de exibição de apresentação para onde deveria estar no início da animação com!!! Esta linha não deve ser necessária !!!. Isso parece funcionar no dispositivo com a versão atual do iOS 7. No entanto, no simulador, o controlador fica visível na posição limpa por pelo menos um quadro.
Desconfio que estou fazendo outra coisa errada e que vou ter problemas com minha solução alternativa, mascarando outro problema.
Alguma ideia sobre o que se passa? Obrigado!