Os eventos do UIScrollView Touch durante a animação não atiram com o AnimateWithDuration: mas funcione bem com as iniciações do UIView:
-
26-09-2019 - |
Pergunta
Eu tenho uma subclasse do UIScrollView que estou rolando programaticamente usando as animações do UIView.
Eu gostaria que o usuário pudesse tocar ou ampliar o uiimageView conteúdo da visualização de rolagem enquanto A animação está ocorrendo.
Isso funcionou bem ao usar uma formulação semelhante a isso:
- (void) scrollSmoothlyatPixelsPerSecond:(float)thePixelsPerSecond {
// distance in pixels / speed in pixels per second
float animationDuration = _scrollView.contentSize.width / thePixelsPerSecond;
[UIView beginAnimations:@"scrollAnimation" context:nil];
[UIView setAnimationCurve: UIViewAnimationCurveLinear];
[UIView setAnimationDuration:animationDuration];
_scrollView.contentOffset = CGPointMake(_scrollView.contentSize.width, 0);
[UIView commitAnimations];
}
Agora, desde o iOS 4.0, o UIView BeginAmations: está desanimado. Então tentei atualizar meu código usando um bloco e o UIView AnimateWithDuration: o rolagem funciona de forma idêntica ao acima.
A diferença chave e enlouquecedora é que, durante a animação, o UIScrollView e outras visualizações que não respondem aos métodos de manuseio de eventos:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
Nem faz :
-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView;
Seja chamado ao tentar aumentar o zoom.
Editar para maior clareza: Nenhuma visão do uiview responde aos eventos de toque. Isso não se limita apenas ao UIScrollView. O Peer do UIScrollView A Uitoolbar não responde aos eventos de toque, nem outros botões que são subvisivos de um colega do UIScrollView. Parece que toda a UIView dos pais está congelada fora da interação do usuário Enquanto a animação está acontecendo. Novamente, após a conclusão da animação, todas as UIViews acima respondem novamente.
Tudo isso é chamado nas iniciações UIView: formulação, independentemente do estado de animação.
Meu AnimateWithDuration: o código é um pouco diferente - mas as diferenças não são materiais. Assim que a animação concluir, os eventos de toque acima são novamente chamados ...
Aqui está meu código animado:
- (void) scrollSmoothlyToSyncPoint:(SyncPoint *) theSyncPoint andContinue:(BOOL)theContinueFlag{
float animationDuration = theSyncPoint.time - [player currentTime];
[UIView animateWithDuration:animationDuration
delay:0
options:UIViewAnimationOptionCurveLinear
animations:^{
[_scrollView setContentOffset:theSyncPoint.contentOffset];
}
completion:^(BOOL finished){
if (theContinueFlag) {
SyncPoint *aSyncPoint = [self nextSyncPoint];
if (aSyncPoint) {
[self scrollSmoothlyToSyncPoint:aSyncPoint andContinue:YES];
}
}
}];
}
O único manipulador de eventos que dispara durante o bloco de animação acima é:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;
Então, pergunta: devo - ignorar a Apple's desanimado Rotule e continue a usar a formulação de iniciação? Devo - reimplementar o zoom e meus outros eventos baseados em toque usando o Hittest? Existe algum conhecimento da diferença na implementação entre blocos de animação que podem me ajudar a enfrentar esse problema? Há algo óbvio que estou perdendo?
Eu sou um novo desenvolvedor da Apple, e então não sei como levar a sério o seu desanimado marcação. Mas se essa API for descontinuada, desaparecer, eu prefiro seguir em uma direção duradoura.
Muito obrigado pela sua atenção.
Solução
Você só precisa incluir a opção UiviewanimationOptionAlowUserInteraction ao invocar a animação como assim:
[UIView animateWithDuration:animationDuration
delay:0
options:(UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction)
<snip>];
Isso é sorrateiro, eu sei! ;)
Re: A tag "desencorajada" - em geral, quando a Apple diz para você não fazer algo em relação ao design de aplicativos que são executados em suas plataformas, geralmente é para o seu próprio bem. Então você está certo em querer adotar blocos de animação em vez da maneira antiga e desajeitada.
Outras dicas
quickthyme
A resposta está correta. Aqui está o trecho de Swift
Swift 4
UIView.animate(
withDuration: 0.3, // specify animation duration here
delay: 0, // specify delay if needed
options: [
UIView.AnimationOptions.allowUserInteraction,
UIView.AnimationOptions.curveLinear
],
animations: {
// animations code
}
)