2012-04-05 13 views
7

Nel momento in cui ricevo touchesBegan, voglio removeFromSuperview la vista che è stata toccata e addSuperview in una nuova vista genitore, e quindi continuare a ricevere tocchi. Tuttavia sto scoprendo che a volte questo non funziona. Nello specifico, touchesMoved e touchesEnded non vengono mai chiamati.iOS: trasferimento della proprietà di UIView mentre si verificano tocchi?

C'è un trucco per farlo funzionare correttamente? Questo è per l'implementazione di un comportamento drag and drop, in cui la vista è inizialmente all'interno di una vista di scorrimento.

Grazie.

risposta

0

È necessario elaborare i tocchi nella panoramica anziché nella visualizzazione che si desidera disattivare. Questo ti permetterà di cambiare la vista senza perdere i tuoi eventi touch. Tuttavia, quando esegui questa operazione, dovrai verificare se il tocco si sta verificando nella visualizzazione secondaria specifica che desideri disattivare. Questo può essere fatto molti modi, ma qui ci sono alcuni metodi per iniziare:

Conversione Rect/Punto a un'altra visualizzazione:

[view convertRect:rect toView:subview]; 
[view convertPoint:point toView:subview]; 

Ecco alcuni metodi per testare se il punto si trova nella vista :

[subView hitTest:point withEvent:nil]; 
CGRectContainsPoint(subview.frame, point); //No point conversion needed 
[subView pointInside:point withEvent:nil]; 

In generale, è preferibile utilizzare UIGestureRecognizers. Ad esempio, se si stesse utilizzando un UIPanGestureRecognizer, si creerebbe un metodo che il riconoscitore di gesti può chiamare e in quel metodo si esegue il proprio lavoro. Per esempio:

- (void) viewPanned:(UIPanGestureRecognizer *)pan{ 
    if (pan.state == UIGestureRecognizerStateBegan){ 
     CGRect rect = subView.frame; 
     newView = [[UIView alloc] initWithFrame:rect]; 
     [subView removeFromSuperview]; 
     [self addSubview:newView]; 
    } else if (pan.state == UIGestureRecognizerStateChanged){ 
     CGPoint point = [pan locationInView:self]; 
     newView.center = point; 
    } else { 
     //Do cleanup or final view placement 
    } 
} 

Poi init il sistema di riconoscimento, assegnato alla destinazione (di solito auto) e aggiunge:

[self addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewPanned:)]]; 

Ora sé (che sarebbe il superview gestione è subviews) risponderà per fare una panoramica dei movimenti.

+0

Non so perché sarebbe. Puoi pubblicare il codice? A proposito, cosa ti impedisce di usare un UIGestureRecognizer? In quasi tutti i casi in cui ho preso in considerazione l'utilizzo di Touches, ho scoperto che sia UIGestureRecognizer sia la sottoclasse UIGestureRecognizer funzionano meglio (e posso riutilizzarli). –

+0

Se stai usando lo stock UIPanGestureRecognizer, 'touchesBegan' non dovrebbe essere nel tuo codice. Dovresti impostare un metodo di destinazione come questo: '- (void) viewPanned: (UIPanGestureRecognizer) pan'. Quando si avvia il riconoscimento, si imposta la sua destinazione: '[[UIPanGestureRecognizer alloc] initWithTarget: self action: @selector (viewPanned :)]'.Questo metodo verrà chiamato ripetutamente e potrai controllare lo stato ed eseguire le azioni appropriate: 'If (pan.state == UIGestureRecognizerStateBegan) {.......}' o 'If (pan.state == UIGestureRecognizerStateChanged {. ....} 'etc ... –

+0

Ho espanso la mia risposta per rispecchiare questo –

7

Invece di:

[transferView removeFromSuperView]; 
[newParentView addSubview:transferView]; 

Utilizzare solo:

[newParentView addSubview:transferView]; 

All'interno della documentazione si afferma "Le viste possono avere solo un superview Se la vista ha già un superview e quello. la vista non è il ricevitore, questo metodo rimuove la superview precedente prima di rendere il ricevitore la sua nuova superview. "

Pertanto non è necessario utilizzare removeFromSuperView perché è gestito da addSubview. Ho notato che removeFromSuperView termina qualsiasi tocco corrente senza chiamare touchEnded. Se si utilizza solo addSubview, i tocchi non vengono interrotti.

+1

Questa dovrebbe essere la risposta accettata in quanto non è necessario gestire il trascinamento nella superview per raggiungere l'obiettivo dell'OP. Semplicemente rimuovendo ** removeFromSuperView ** il trucco. Grazie ** walapu **. – walkingbrad

+0

Ottima risposta, questo è stato molto utile! – Max

Problemi correlati