Un'osservazione su come fare affidamento sulla velocità in UIPanGestureRecognizer
: Non conosco la tua esperienza, ma ho trovato che la velocità generata dal simulatore del sistema non è terribilmente utile. (È ok sul dispositivo, ma problematico sul simulatore.)
Se si esegue rapidamente una panoramica e si interrompe bruscamente, attendere e solo dopo aver terminato il gesto (ad esempio, l'utente avvia uno scorrimento, si rende conto che non era quello che volevano , quindi si fermano e quindi rilasciano il dito), la velocità riportata da velocityInView:
allo stato UIGestureRecognizerStateEnded
quando il dito è stato rilasciato sembra essere la velocità veloce prima che mi fermassi e aspettassi, mentre la velocità giusta in questo esempio sarebbe zero (o vicino zero). In breve, la velocità riportata è quella che era giusto prima della fine della padella, ma non la velocità alla fine della padella stessa.
Alla fine ho calcolato manualmente la velocità. (Sembra sciocco che sia necessario, ma non ho visto alcun modo se volevo ottenere la velocità finale della padella.) In conclusione, quando lo stato è UIGestureRecognizerStateChanged
tengo traccia delle attuali e precedenti translationInView
CGPoint così come il tempo, e quindi utilizzando quei valori quando ero nello UIGestureRecognizerStateEnded
per calcolare la velocità finale effettiva. Funziona piuttosto bene.
Ecco il mio codice per il calcolo della velocità. Mi è capitato di non usare la velocità per calcolare la velocità dell'animazione, ma piuttosto la sto usando per determinare se l'utente ha effettuato una panoramica sufficiente o ha effettuato uno sfarfallio abbastanza velocemente da consentire alla vista di spostarsi oltre la metà dello schermo e quindi innescando l'animazione tra le visualizzazioni, ma il concetto di calcolare la velocità finale sembra applicabile a questa domanda. Ecco il codice:
- (void)handlePanGesture:(UIPanGestureRecognizer *)gesture
{
static CGPoint lastTranslate; // the last value
static CGPoint prevTranslate; // the value before that one
static NSTimeInterval lastTime;
static NSTimeInterval prevTime;
CGPoint translate = [gesture translationInView:self.view];
if (gesture.state == UIGestureRecognizerStateBegan)
{
lastTime = [NSDate timeIntervalSinceReferenceDate];
lastTranslate = translate;
prevTime = lastTime;
prevTranslate = lastTranslate;
}
else if (gesture.state == UIGestureRecognizerStateChanged)
{
prevTime = lastTime;
prevTranslate = lastTranslate;
lastTime = [NSDate timeIntervalSinceReferenceDate];
lastTranslate = translate;
[self moveSubviewsBy:translate];
}
else if (gesture.state == UIGestureRecognizerStateEnded)
{
CGPoint swipeVelocity = CGPointZero;
NSTimeInterval seconds = [NSDate timeIntervalSinceReferenceDate] - prevTime;
if (seconds)
{
swipeVelocity = CGPointMake((translate.x - prevTranslate.x)/seconds, (translate.y - prevTranslate.y)/seconds);
}
float inertiaSeconds = 1.0; // let's calculate where that flick would take us this far in the future
CGPoint final = CGPointMake(translate.x + swipeVelocity.x * inertiaSeconds, translate.y + swipeVelocity.y * inertiaSeconds);
[self animateSubviewsUsing:final];
}
}
Non funziona in iOS 6 perché la traduzione finale e l'ultima traduzione è la stessa in "UIGestureRecognizerStateEnded", quindi la velocità finale è sempre 0. – an0
Grazie, vedo. È un problema di simulatore. Ho lanciato un bug report ad Apple. – an0
Ho modificato la fonte (cambiando alcuni nomi di variabili) per evitare di evitare questa confusione. Questo codice ha funzionato bene, ma si spera che i nuovi nomi delle variabili rendano persino un po 'meno confusionario. Grazie per aver segnalato il bug ad Apple. – Rob