UIScrollView eventi touch durante l'animazione non sparare con animateWithDuration: ma funzionano bene con UIView beginAnimations:
-
26-09-2019 - |
Domanda
Ho una sottoclasse UIScrollView che sto programmazione Scorrimento usando animazioni UIView.
Mi piacerebbe che l'utente sia in grado di attingere o zoom nel contenuto UIImageView del Rotolo Visualizza , mentre l'animazione è in corso.
Questo ha lavorato bene durante l'utilizzo di una formulazione simile a questo:
- (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];
}
Ora, dal momento che iOS 4.0, UIView beginAnimations: è scoraggiato. Così ho cercato di aggiornare il mio codice utilizzando un blocco e UIView animateWithDuration: Lo scorrimento funziona in modo identico a quanto sopra.
La chiave e la differenza esasperante è che durante l'animazione, l'UIScrollView e altre viste non più rispondere ai metodi di manipolazione di evento:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
Né:
-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView;
get chiamato quando si cerca di zoom.
Modifica per chiarezza: No UIView presenti risponde al tocco eventi. Questo non è limitato al solo UIScrollView. pari del UIScrollView un UIToolbar non risponde a eventi touch, né altri pulsanti che sono subviews di un pari alla UIScrollView. Sembra che l'intero UIView genitore è congelato fuori interazione con l'utente , mentre l'animazione è in corso . Ancora una volta, dopo il completamento di animazione, tutti i UIViews sopra sono nuovamente reattivo.
Questi tutti fatevi chiamata negli beginAnimations UIView:. Formulazione indipendentemente dallo stato di animazione
Il mio animateWithDuration: il codice è un po 'diverso - ma le differenze non sono rilevanti. Non appena il completamento del animazione, gli eventi touch di cui sopra sono di nuovo chiamati ...
Ecco il mio codice animato:
- (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];
}
}
}];
}
L'unico gestore di eventi che viene generato durante il blocco di animazione qui sopra è:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;
Quindi, domanda: Dovrei - ignoro di Apple scoraggiato etichetta e continuare a utilizzare la formulazione BeginAnimation? Dovrei - reimplementare zoom e gli altri miei eventi touch-based utilizzando hitTest? C'è una certa conoscenza della differenza di realizzazione tra i blocchi di animazione che possono aiutare me affrontare questo problema? C'è qualcosa di ovvio che mi manca?
Sono un nuovo sviluppatore di Apple, e quindi non so quanto seriamente a prendere il loro scoraggiato tag. Ma se questa API sarà deprecato poi scomparire, preferirei muoversi in una direzione duratura.
Grazie mille per la vostra attenzione.
Soluzione
Hai solo bisogno di includere l'opzione UIViewAnimationOptionAllowUserInteraction quando si richiama l'animazione in questo modo:
[UIView animateWithDuration:animationDuration
delay:0
options:(UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction)
<snip>];
Questo è uno subdolo, lo so! ;)
Re: Il tag "Scoraggiato" - In generale, quando Apple dice di non fare qualcosa per quanto riguarda la progettazione di applicazioni che girano sulle loro piattaforme, di solito è per il tuo bene. Quindi lei ha ragione nel voler adottare blocchi di animazione al posto del vecchio modo goffo.
Altri suggerimenti
di quickthyme
è corretta. Ecco il frammento di 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
}
)