2012-04-04 2 views
7

Я реализую простую пасьянс iOS, позволяющую пользователю перетаскивать карты обычным способом. Карты представлены подклассом UIViewCardView. Все виды карт - это братья и сестры, которые являются подземелиями SolitaireView. Следующий фрагмент кода пытается «принести карту на фронт», так что она выше всех других точек зрения, как его перетаскивании:UIView bringSubviewToFront: делает * не * приносит вид спереди

-(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]; 
     ... 
    } 
} 

К сожалению, г-приказание карты остается неизменным во время торможения. На изображениях ниже я перетаскиваю Короля. Обратите внимание на то, как это правильно на вершине Девять в леве изображения, но неверно по второй (по всей стеке на самом деле) в правом изображении:

enter image description hereenter image description here

Я также попытался изменить layer.zPosition свойства, как ну безрезультатно. Как я могу отобразить карту на передней панели во время перетаскивания? Я озадачен.

+0

Я обнаружил, что 'bringSubviewToFront:' запускает флаг вида по «needsLayout» должен быть установлен. Мой метод 'layoutSubviews' также вызывал' bringSubviewToFront: 'таким образом, возвращая все z-порядки представления обратно в исходное состояние! – wcochran

+0

Тогда какое решение для этого? У меня также есть такие же требования, когда из списка карточек, если я выбираю какую-либо карточку среднего ордера, он должен подняться, а затем выйти на фронт. но моя анимация не работает из-за bringSubviewToFront: method – Mrunal

+0

Если вы придерживаетесь подклассов UIView, тогда вам нужно отметить перетаскиваемую карту, чтобы layoutSubviews мог разместить ее сверху. Я фактически переключился на использование CALayers, как указано ниже. – wcochran

ответ

8

Подтверждено. bringSubviewToFront: вызывает layoutSubview для вызова. Поскольку моя версия layoutSubviews устанавливает z-порядки во всех представлениях, это отменяло z-порядок, который я устанавливал в коде touchesBegan:withEvent выше. Apple должна упомянуть об этом побочном эффекте в документации bringSubviewToFront.

Вместо подкласса UIView я создал подкласс CALayer по имени CardLayer. Я обрабатываю прикосновение в моем подклассе KlondikeView, как показано ниже. topZPosition - это экземпляр var, который отслеживает наивысшую zPosition всех карт. Обратите внимание, что изменение zPosition обычно анимированный - я повернуть это в коде ниже:

-(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

Я думаю, что использование 'UIView' для игры в карты, возможно, было плохим выбором дизайна - я не думаю, что они действительно были предназначены для этого. Я думаю, что я отступлю и вместо этого использую 'CALayer'. – wcochran

Смежные вопросы