2011-01-07 14 views
35

Oggi, durante il mio periodo di creatività, ho svolto alcune ricerche approfondite su come rubare i tocchi da un UIScrollView e inviarli istantaneamente a una sottoview specifica, mantenendo il comportamento predefinito per il resto della visualizzazione di scorrimento. Considera di avere un UIPickerView all'interno di UITableView. Il comportamento predefinito è che se si trascina il dito sulla vista del selettore, la vista di scorrimento scorrerà e la vista del selettore rimarrà invariata.Come rubare i tocchi da UIScrollView?

La prima cosa che ho provato è stato quello di ignorare

- (BOOL)touchesShouldCancelInContentView:(UIView *)view 

e semplicemente proibisce l'UIScrollView per annullare tocchi all'interno della vista selettore. Funziona, ma ha uno spiacevole effetto collaterale. Vorresti che la vista del selezionatore rispondesse immediatamente e quindi dovrai impostare delaysContentTouches su NO. Il problema è che non vuoi che il resto della vista tabella risponda immediatamente, perché se la cella di visualizzazione tabella verrà sempre evidenziata per alcuni millisecondi prima dell'avvio dello scorrimento.

La seconda cosa che ho cercato è stato quello di ignorare

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 

perché avevo letto che la vista di scorrimento si ritorna sempre, in modo che possa "rubare" i tocchi dai suoi subviews e poi inviarli alla visualizzazione secondaria se non fossero di interesse per la vista di scorrimento. Tuttavia, questo non è più vero. L'implementazione predefinita di hitTest di UIScrollView: withEvent: restituisce effettivamente la sottoview che dovrebbe ricevere il tocco. Invece utilizza i gesti riconoscitori per intercettare i tocchi.

Quindi la terza cosa che ho tentato è stata quella di implementare il mio riconoscimento dei gesti e farlo fallire se il tocco era al di fuori della vista del selettore e in caso contrario riusciva. Poi ho impostato tutti i sistemi di riconoscimento gesto della vista di scorrimento a fallire a meno che il mio gesto non è riuscita riconoscitore utilizzando il seguente codice:

for (UIGestureRecognizer * gestureRecognizer in self.tableView.gestureRecognizers) 
{ 
    [gestureRecognizer requireGestureRecognizerToFail:myRecognizer]; 
} 

Ciò, infatti, ruba i tocchi dalla vista di scorrimento, ma la vista selettore non li riceve. Così ho pensato che forse potrei semplicemente inviare tutti i tocchi che il mio gesto riconoscitore riceve utilizzando questo codice:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    for (UITouch *touch in touches) 
     [touch.view touchesBegan:touches withEvent:event]; 
} 

Il codice di cui sopra è una versione semplificata. Mi assicuro inoltre che la vista sia una vista di selezione (o una delle sue sottoview) e che imposti lo stato appropriato per il riconoscimento di gesti come accennato in precedenza. Ho anche fatto lo stesso per annullato, concluso e spostato. Tuttavia, la vista del selettore continuava a non rispondere.

Ho provato anche un'ultima cosa prima di tornare al mio lavoro normale. Durante la mia vasta googling ho letto che UIScrollViews nidificati magicamente lavorato dal 3.x, così ho provato a mettere la mia vista selettore all'interno di un UIScrollView nidificato e impostare le seguenti proprietà su di essa:

scrollView.delaysContentTouches = NO; 
scrollView.canCancelContentTouches = NO; 

Come ci si aspetterebbe il rotolo esterno la vista non ha trattato la vista di scorrimento interna in modo diverso da come ha trattato la vista di selezione, quindi la vista di scorrimento interna non ha ricevuto i tocchi. Ho pensato che fosse un campo lungo, ma era abbastanza semplice da implementare, quindi ho pensato che valesse la pena dare un colpo.

Quello che so è che UIScrollView ha un riconoscitore di gesti chiamato UIScrollViewDelayedTouchesBeganGestureRecognizer che intercetta i tocchi e li invia alla sottoview appropriata dopo 150 (?) Ms. Sto pensando che dovrei essere in grado di scrivere un riconoscitore simile che fa fallire i riconoscitori predefiniti della vista di scorrimento e invece di ritardare i tocchi li invia immediatamente alla vista di selezione.Quindi, se qualcuno sa come scrivere un riconoscimento di questo tipo, fatemelo sapere e se avete altre soluzioni al problema, vi prego di condividerla.

Grazie per aver letto l'intera domanda e anche se non si conosce la risposta, si potrebbe comunque passare la domanda in modo da ottenere più attenzione (si spera che qualcuno possa rispondere). Grazie! :)

risposta

32

A volte devi fare la domanda prima di poter trovare la risposta. Dan Ray ha avuto un problema simile e l'ha risolto con una soluzione molto diversa.

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event 
{ 
    UIView* result = [super hitTest:point withEvent:event]; 

    if ([result.superview isKindOfClass:[UIPickerView class]]) 
    { 
     self.scrollEnabled = NO; 
    } 
    else 
    { 
     self.scrollEnabled = YES;  
    } 
    return result; 
} 

Ho testato il codice e funziona anche per me. Tuttavia, questo non significa rubare i tocchi dalla vista di scorrimento, quindi se qualcuno sa come rubare realmente i tocchi sarebbe grandioso.

Fonte: UIPickerView inside UITableView.tableFooterView doesn't receive drag touches

+0

Dal momento che questa è ancora l'unica risposta, io l'accetto come mia risposta, ma se hai una soluzione migliore, non esitare a condividerla! –

+0

Questa è la mia soluzione preferita. È snello e meschino e funziona. Molte grazie! – DrMickeyLauer

+1

Eccellente, per le mie esigenze l'ho cambiato in '([risultato isKindOfClass: [UITableView class]] || [result.superview isKindOfClass: [UITableView class]] || [result.superview isKindOfClass: [UITableViewCell class]])) ' – Diziet

Problemi correlati