2012-04-04 12 views
7

Estoy implementando un sencillo juego de solitario iOS que permite al usuario arrastrar las tarjetas de la manera habitual. Las tarjetas se representan con la subclase UIViewCardView. Todas las vistas de tarjeta son hermanos que son subvistas de SolitaireView. El siguiente fragmento intenta "llevar una tarjeta en la parte delantera" de modo que está por encima de todos los otros puntos de vista, ya que está siendo arrastrado:UIView bringSubviewToFront: does * not * bring view to front

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    UITouch *touch = [touches anyObject]; 
    if (touch.view.tag == CARD_TAG) { 
     CardView *cardView = (CardView*) touch.view; 
     ... 
     [self bringSubviewToFront:cardView]; 
     ... 
    } 
} 

Desafortunadamente, el orden Z de la tarjeta se mantiene sin cambios durante el arrastre. En las imágenes de abajo, estoy arrastrando al Rey. Observe cómo es correcta en la parte superior del Nueve en la imagen izquierda, pero es incorrectamente en los dos (debajo de toda la pila en realidad) en la imagen de la derecha:

enter image description hereenter image description here

También probé alterar la propiedad layer.zPosition como bien en vano. ¿Cómo puedo llevar la vista de la tarjeta al frente durante el arrastre? Estoy desconcertado.

+0

descubrí que 'bringSubviewToFront:' desencadena la bandera de la vista 'needsLayout' a establecer. Mi método 'layoutSubviews' también llamaba a' bringSubviewToFront: 'volviendo todas las z-órdenes de vista a su estado inicial. – wcochran

+0

Entonces, ¿cuál es la solución para esto? También estoy teniendo el mismo tipo de requisitos, donde de la lista de tarjetas, si selecciono cualquiera de la tarjeta de orden intermedia, debería aparecer, luego pasar al frente. pero mi animación no está funcionando debido a bringSubviewToFront: método – Mrunal

+0

Si te quedas con el uso de subclases de UIView, entonces necesitas marcar la tarjeta que se está arrastrando para que layoutSubviews pueda colocarlo en la parte superior. De hecho, cambié a usar CALayers como se menciona a continuación. – wcochran

Respuesta

8

Confirmado. bringSubviewToFront: provoca que se invoque layoutSubview. Dado que mi versión de layoutSubviews establece los z-orders en todas las vistas, esto estaba deshaciendo el orden z que estaba configurando en el código touchesBegan:withEvent anterior. Apple debería mencionar este efecto secundario en la documentación bringSubviewToFront.

En lugar de utilizar una subclase UIView, creé una subclase CALayer llamada CardLayer. Manejo el toque en mi subclase KlondikeView como se detalla a continuación. topZPosition es una instancia var que rastrea la zPosition más alta de todas las tarjetas. Tenga en cuenta que la modificación de la zPosition suele animados - Me desactivar esta opción en el código de abajo:

-(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { 
    UITouch *touch = [touches anyObject]; 
    CGPoint touchPoint = [touch locationInView:self]; 
    CGPoint hitTestPoint = [self.layer convertPoint:touchPoint 
              toLayer:self.layer.superlayer]; 
    CALayer *layer = [self.layer hitTest:hitTestPoint]; 

    if (layer == nil) return; 

    if ([layer.name isEqual:@"card"]) { 
    CardLayer *cardLayer = (CardLayer*) layer; 
    Card *card = cardLayer.card; 

    if ([self.solitaire isCardFaceUp:card]) { 
     //...                            
     [CATransaction begin]; // disable animation of z change                 
     [CATransaction setValue:(id)kCFBooleanTrue 
         forKey:kCATransactionDisableActions];    
     cardLayer.zPosition = topZPosition++; // bring to highest z 

     // ... if card fan, bring whole fan to top 

     [CATransaction commit]; 
     //...                            
    } 
    // ...                            
    } 

} 
+4

Creo que usar 'UIView' para jugar a las cartas puede haber sido una mala elección de diseño. No creo que realmente hayan sido diseñadas para esto. Creo que daré un paso atrás y usaré 'CALayer' en su lugar. – wcochran

Cuestiones relacionadas