Risposta ai tocchi Inizia con UIPickerView invece di UIView

Ho un UIPickerView che si sbiadisce al 20% alfa quando non è in uso. Voglio che l’utente sia in grado di toccare il selettore e farlo dissolvere nuovamente.

Posso farlo funzionare se applico un metodo Began sulla vista principale, ma funziona solo quando l’utente tocca la vista. Ho provato a sottoclass UIPickerView e ho avuto un touch in cucina, ma non ha funzionato.

Immagino che sia qualcosa a che fare con la catena del risponditore, ma non riesco a risolverlo.

Ho cercato una soluzione a questo problema per oltre una settimana. Ti sto rispondendo anche se la tua domanda ha più di un anno sperando che questo aiuti gli altri.

Scusa se la mia lingua non è molto tecnica, ma sono piuttosto nuova allo sviluppo di Objective-C e iPhone.

Sottoclassi UIpickerView è il modo giusto per farlo. Ma devi sovrascrivere il - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event . Questo è il metodo chiamato ogni volta che tocchi lo schermo e restituisce la vista che reagirà al touch. In altre parole, la vista di cui si touchesBegan:withEvent: method.

UIPickerView ha 9 sottoview! Nell’implementazione della class UIPickerView - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event non restituirà self (questo significa che i touchesBegan:withEvent: tu scrivi nella sottoclass non verrà chiamato) ma restituirà una sottoview, esattamente la vista all’indice 4 (una sottoclass non documentata chiamata UIPickerTable).

Il trucco consiste nel rendere - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event per restituire self modo da avere il controllo sui touchesBegan:withEvent: touchesMoved:withEvent: and touchesEnded:withEvent: methods.

In questi metodi, per mantenere le funzionalità standard di UIPickerView, è necessario ricordarsi di richiamarli di nuovo ma nella sottoview di UIPickerTable.

Spero che abbia senso. Non riesco a scrivere il codice ora, appena sarò a casa modificherò questa risposta e aggiungerò del codice.

Ecco un codice che fa ciò che vuoi:

 @interface TouchDetectionView : UIPickerView { } - (UIView *)getNextResponderView:(NSSet *)touches withEvent:(UIEvent *)event; @end @implementation TouchDetectionView - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UIView * hitTestView = [self getNextResponderView:touches withEvent:event]; [hitTestView touchesBegan:touches withEvent:event]; } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { UIView * hitTestView = [self getNextResponderView:touches withEvent:event]; [hitTestView touchesMoved:touches withEvent:event]; } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { UIView * hitTestView = [self getNextResponderView:touches withEvent:event]; [hitTestView touchesEnded:touches withEvent:event]; } - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { UIView * hitTestView = [self getNextResponderView:touches withEvent:event]; [hitTestView touchesCancelled:touches withEvent:event]; } - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { return self; } - (UIView *)getNextResponderView:(NSSet *)touches withEvent:(UIEvent *)event { UITouch * touch = [touches anyObject]; CGPoint point = [touch locationInView:self]; UIView * hitTestView = [super hitTest:point withEvent:event]; return ( hitTestView == self ) ? nil : hitTestView; } 

Entrambe le risposte di cui sopra sono state molto utili, ma ho un UIPickerView nidificato all’interno di un UIScrollView. Sto anche facendo rendering continuo altrove sullo schermo mentre la GUI è presente. Il problema è che UIPickerView non si aggiorna completamente quando: viene toccata una riga non selezionata, il selettore viene spostato in modo che due righe si trovino a ridosso dell’area di selezione, oppure una riga viene trascinata ma il dito scorre all’esterno di UIPickerView. Quindi, non viene spostato UIScrollView che il selettore si aggiorna istantaneamente. Questo risultato è brutto.

La causa del problema: il mio rendering continuo impediva all’animazione di UIPickerView di ottenere i cicli della CPU necessari per completare, quindi di mostrare la selezione attuale corretta. La mia soluzione, che funziona, era questa: nei touchesEnded:withEvent: di UIPickerView touchesEnded:withEvent: esegui qualcosa per mettere in pausa il mio rendering per un breve periodo. Ecco il codice:

 #import "SubUIPickerView.h" @implementation SubUIPickerView - (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { [pickerTable touchesBegan:touches withEvent:event]; } - (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event { [pickerTable touchesMoved:touches withEvent:event]; } - (void) touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event { [singleton set_secondsPauseRendering:0.5f]; // <-- my code to pause rendering [pickerTable touchesEnded:touches withEvent:event]; } - (void) touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event { [pickerTable touchesCancelled:touches withEvent:event]; } - (UIView*) hitTest:(CGPoint)point withEvent:(UIEvent*)event { if (CGRectContainsPoint(self.bounds, point)) { if (pickerTable == nil) { int nSubviews = self.subviews.count; for (int i = 0; i < nSubviews; ++i) { UIView* view = (UIView*) [self.subviews objectAtIndex:i]; if ([view isKindOfClass:NSClassFromString(@"UIPickerTable")]) { pickerTable = (UIPickerTable*) view; break; } } } return self; // ie, *WE* will respond to the hit and pass it to UIPickerTable, above. } return [super hitTest:point withEvent:event]; } @end 

e quindi l'intestazione, SubUIPickerView.h:

 @class UIPickerTable; @interface SubUIPickerView : UIPickerView { UIPickerTable* pickerTable; } @end 

Come ho detto, funziona. Rendering pause per un ulteriore 1/2 secondo (si interrompe già quando si scorre UIScrollView) consentendo di completare l'animazione UIPickerView. L'uso di NSClassFromString () significa che non stai usando API non documentate. Messing con la catena di risponditori non era necessario. Grazie a checcco e Tylerc230 per avermi aiutato a trovare la mia soluzione!

Imposta canCancelContentTouches e ritardiContentTouches della vista padre su NO, che ha funzionato per me