2012-04-04 49 views
7

我正在實施一個簡單的iOS紙牌遊戲,允許用戶以通常的方式拖動卡片。卡片由UIView子類CardView表示。所有卡片視圖都是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]; 
     ... 
    } 
} 

不幸的是,該卡的Z順序在拖動過程中保持不變。在下面的圖片中,我拖着國王。注意它是如何正確地在頂部的左側圖像中的九,但是是不正確的下二(整個堆棧下實際上)右圖像中:

enter image description hereenter image description here

我也試過改變layer.zPosition財產以至無濟於事。 在拖動過程中,如何將卡片視圖放到前面?我很困惑。

+0

我發現'bringSubviewToFront:'觸發視圖的「needsLayout」標誌被設置。我的'layoutSubviews'方法也調用'bringSubviewToFront:',從而將所有的視圖z-order恢復到它們的初始狀態! – wcochran 2012-04-04 22:13:36

+0

那麼這是什麼解決方案?我也有同樣的要求,從列表中,如果我選擇任何中間順序卡,它應該出現,然後來到前面。但我的動畫因爲使用bringSubviewToFront而不工作:方法 – Mrunal 2013-03-21 14:25:25

+0

如果你堅持使用UIView子類,那麼你需要標記被拖動的卡片,這樣layoutSubviews可以將它放在最前面。我實際上轉向使用CALayers,如下所述。 – wcochran 2013-03-22 15:11:13

回答

8

確認。 bringSubviewToFront:導致layoutSubview被調用。由於我的layoutSubviews版本在所有視圖上設置了z-次序,這就是我在上面的touchesBegan:withEvent代碼中設置的z-次序的撤銷。蘋果應該在bringSubviewToFront文檔中提到這種副作用。

代替使用UIView子類,我創建了一個名爲CardLayer的子類CALayer。我在下面列出的KlondikeView子類中處理觸摸。 topZPosition是一個實例var,用於跟蹤所有卡的最高z位置。需要注意的是修改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 2012-04-06 18:07:10