Respondendo a toquesBegan in UIPickerView em vez de UIView

Eu tenho um UIPickerView que fica desbotado para 20% alfa quando não estiver em uso. Eu quero que o usuário possa tocar no selecionador e fazê-lo desaparecer novamente.

Eu posso fazê-lo funcionar se eu colocar um método toques de feijão na Vista principal, mas isso só funciona quando o usuário toca na Vista. Eu tentei subclassificar o UIPickerView e começar a tocar lá, mas não funcionou.

Eu estou supondo que é algo a ver com a cadeia Responder, mas não consigo resolver isso.

Eu tenho procurado por uma solução para este problema por mais de uma semana. Eu estou respondendo a você mesmo se você tiver mais de um ano de idade esperando que isso ajude os outros.

Desculpe se meu idioma não é muito técnico, mas sou muito novo no desenvolvimento do Objective-C e do iPhone.

Subsorting O UIpickerView é o caminho certo para isso. Mas você deve replace o método de - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event . Esse é o método chamado sempre que você toca na canvas e retorna a visão que reagirá ao toque. Em outras palavras, a visualização cujo touchesBegan:withEvent: será chamado.

O UIPickerView possui 9 subvisualizações! Na implementação da class UIPickerView - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event não retornará self (isso significa que o touchesBegan:withEvent: você escreve na subclass não será chamado) mas retornará uma subvisualização, exatamente a visualização no índice 4 (uma subclass não documentada chamada UIPickerTable).

O truque é fazer com que o método de - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event retorne para que você tenha controle sobre os touchesBegan:withEvent: touchesMoved:withEvent: e touchesEnded:withEvent: .

Nesses methods, para manter as funcionalidades padrão do UIPickerView, você DEVE se lembrar de chamá-las novamente, mas na subvisão UIPickerTable.

Espero que isto faça sentido. Não consigo escrever código agora, assim que estiver em casa, vou editar essa resposta e adicionar algum código.

Aqui está um código que faz o que você quer:

 @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; } 

Ambas as respostas acima foram muito úteis, mas eu tenho um UIPickerView nested dentro de um UIScrollView. Eu também estou fazendo renderização contínua em outro lugar na canvas enquanto a GUI está presente. O problema é que o UIPickerView não é totalmente atualizado quando: uma linha não selecionada é tocada, o selecionador é movido para que duas linhas ocupem a área de seleção ou uma linha é arrastada, mas o dedo desliza para fora do UIPickerView. Então, não é até que o UIScrollView seja movido para que o selecionador seja atualizado instantaneamente. Este resultado é feio.

A causa do problema: minha renderização contínua estava impedindo a animação do UIPickerView de obter os ciclos de CPU necessários para concluir, portanto, para mostrar a seleção atual correta. Minha solução – o que funciona – foi a seguinte: em touchesEnded:withEvent: ‘s touchesEnded:withEvent: execute algo para pausar minha renderização por um tempo curto. Aqui está o código:

 #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 depois o header, SubUIPickerView.h:

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

Como eu disse, isso funciona. A renderização faz uma pausa por mais um segundo (já faz uma pausa quando você desliza o UIScrollView), permitindo que a animação UIPickerView seja concluída. Usar NSClassFromString () significa que você não está usando APIs não documentadas. Mexer com a corrente do Responder não era necessário. Obrigado ao checcco e ao Tylerc230 por me ajudar a criar minha própria solução!

Defina canCancelContentTouches e delaysContentTouches of parent view como NO, isso funcionou para mim