2009-05-18 16 views
7

Si prega di qualcuno può aiutare a ordinare un noob fuori? Ho postato questo problema su vari forum e non ho ricevuto risposte, mentre molte ricerche per altre risposte sono diventate stackOverflow, quindi spero che questo sia il posto giusto.UIScrollView tocchi vs tocchi subview

Ho un BeachView.h (sottoclasse di UIScrollView, immagine di una spiaggia sabbiosa) coperto con un numero casuale di Stone.h (sottoclasse di UIImageView, un PNG casuale di una pietra, userInteractionEnabled = SÌ per accettare tocchi).

Se l'utente tocca e si sposta sulla spiaggia, deve scorrere. Se l'utente tocca una pietra, deve chiamare il metodo "touchedStone". Se l'utente tocca la spiaggia dove non c'è pietra, deve chiamare il metodo "touchedBeach".

Ora, mi rendo conto che sembra semplice. Tutti e tutti mi dicono che se c'è qualcosa su un UIScrollView che accetta tocca che dovrebbe passare il controllo su di esso. Quindi quando tocco e trascino, dovrebbe scorrere; ma se tocco, ed è su una pietra, dovrebbe ignorare i rubinetti sulla spiaggia e accettare i rubinetti di pietra, sì?

Tuttavia, sembra che entrambe le visualizzazioni stiano accettando il tocco e chiamando sia touchedStone AND touchedBeach. Inoltre, il tap alla spiaggia viene eseguito per primo, quindi non posso nemmeno inserire un flag di tipo "if touchedStone then do not run touchBeach".

Ecco un po 'di codice. Su BeachView.m


- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    if (self.decelerating) { didScroll = YES; } 
     else { didScroll = NO; } 

    UITouch *touch = [[event allTouches] anyObject]; 
    CGPoint touchLocation = [touch locationInView:touch.view]; 
    NSLog(@"touched beach = %@", [touch view]); 
    lastTouch = touchLocation; 
    [super touchesBegan:touches withEvent:event]; 
} 

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { 
    didScroll = YES; 
    [super touchesMoved:touches withEvent:event]; 
} 

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 
    if (didScroll == NO && isPaused == NO) { 
      [self touchedBeach:YES location:lastTouch]; 
    } 
    [super touchesEnded:touches withEvent:event]; 
} 

Su Stone.m


-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    [parent stoneWasTouched]; // parent = ivar pointing from stone to beachview 
} 

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 
    UITouch *touch = [[event allTouches] anyObject]; 
    CGPoint touchLocation = [touch locationInView:touch.view]; 
    NSLog(@"touched stone = %@", [touch view]); 
    [parent touchedStone:YES location:touchLocation]; 
} 

Dopo un rubinetto di pietra, La mia NSLog assomiglia a questo:


Touched beach = <BeachView: 0x1276a0> 
ran touchedBeach 
Touched Stone = <Stone: 0x1480c0> 
ran touchedStone 

Quindi è effettivamente in esecuzione entrambi. Ciò che è ancora più strano è che se prendo i tocchi Began e tocchi Fine di Stone.m ma lasci userInteractionEnabled = YES, il beachView registra entrambi i tocchi, ma restituisce la Pietra come la vista che ha toccato (la seconda volta).


Touched beach = <BeachView: 0x1276a0> 
ran touchedBeach 
Touched beach = <Stone: 0x1480c0> 
ran touchedBeach 

Quindi PER FAVORE, ho cercato di ordinare questo per giorni. Come faccio a fare in modo che una pietra maschiata richiami solo touchedStone e le chiamate a una spiaggia toccata toccano soloBeach? Dove sto andando male?

risposta

2

Prima di iPhone OS 3.0, il metodo hitTest: withEvent: UIScrollView restituisce sempre self in modo che riceva l'UIEvent direttamente, inoltrandolo solo alla sottoview appropriata se e quando determina che non è correlato allo scorrimento o allo zoom.

non ho potuto commentare su iPhone OS 3.0, come è sotto NDA, ma controllare "osserva iPhone SDK di uscita per iPhone OS 3.0 beta 5" il vostro :)

Se avete bisogno di indirizzare pre-3.0, è potrebbe ignorare hitTest: withEvent: in BeachView e impostare un flag per ignorare il prossimo tocco sulla spiaggia se il CGPoint è effettivamente in una pietra.

Ma hai provato a spostare semplicemente le chiamate a [super-tocchi *: conEvent:] dalla fine dei metodi sovrascritti all'inizio? Ciò potrebbe causare prima il colpetto di pietra.

+0

mi sono trasferito [super] per l'inizio dei metodi e ha fatto la differenza. Registra ancora due tap ma almeno ora sta dicendo 1-beginBeach 2-beginStone 3-endedBeach 4-endedStone, quindi c'è il tempo di far apparire una bandiera lì. Stavo solo guardando HitTest ma quando ha iniziato a parlare di CAlayers vs UIviews sembrava un libro che non ero ancora pronto ad aprire. Darò un altro colpo. Grazie Hatfinch, -k. –

3

È vero, iPhone SDK 3.0 e versioni successive, non passare i tocchi a -touchesBegan: e - touchesEnded: ** UIScrollview ** metodi di sottoclasse più.È possibile utilizzare i metodi touchesShouldBegin e touchesShouldCancelInContentView che non corrispondono.

Se si desidera veramente ottenere questo tocco, è necessario un mod che consenta questo.

nella sottoclasse del UIScrollView l'override del metodo hitTest in questo modo:

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

    UIView *result = nil; 
    for (UIView *child in self.subviews) 
    if ([child pointInside:point withEvent:event]) 
     if ((result = [child hitTest:point withEvent:event]) != nil) 
     break; 

    return result; 
} 

Questo passerà a voi sottoclasse questo tocca, tuttavia non è possibile annullare i tocchi di UIScrollView superclasse.

0

Ho avuto un problema simile con un simpleView e viene aggiunto a una scrollView, e ogni volta che ho toccato la simpleView, il scrollView utilizzato per ottenere il tatto e al posto del SimpleView, il scrollView spostato. Per evitare ciò, ho disabilitato l'aggancio dello scrollView quando l'utente ha toccato lo simpleView e in caso contrario lo scorrimento è abilitato.

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

    UIView *result = [super hitTest:point withEvent:event] ; 
    if (result == simpleView) 
    { 
     scrollView.scrollEnabled = NO ; 
    } 
    else 
    { 
     scrollView.scrollEnabled = YES ; 
    } 

    return result ; 

} 
Problemi correlati