2012-04-04 13 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オーダーは、ドラッグ中に変更されません:次のスニペットは、それがドラッグされているとして、それは他のすべてのビューの上にあるように「前にカードを持って来る」しようとします。下の画像では、私は王をドラッグしています。私としてもlayer.zPositionプロパティを変更しようとした

enter image description hereenter image description here

:それは左上の画像でナインを上に正しくあるが、右の画像に(実際には、スタック全体の下で)2の下に間違っているかに注目してくださいよく無駄に。 ドラッグ中にカードビューを前面に表示するにはどうすればよいですか?私は神秘的です。

+0

私は 'bringSubviewToFrontがあることを発見:'設定するビューの「needsLayout」フラグをトリガします。私の 'layoutSubviews'メソッドは' bringSubviewToFront: 'も呼び出していたので、すべてのビューzオーダーを元の状態に戻しました! – wcochran

+0

それでは、この解決策は何ですか?私も同じ種類の要件を持っています。カードのリストから、中位のカードのいずれかを選択すると、カードが出てきて正面に来るはずです。私のアニメーションはbringSubviewToFrontのために機能しません:メソッド – Mrunal

+0

UIViewサブクラスを使用してスティックする場合、ドラッグするカードをマークして、layoutSubviewsを上に置く必要があります。私は実際に下記のようにCALayersを使用するように切り替えました。 – wcochran

答えて

8

が確認されました。 bringSubviewToFront:により、layoutSubviewが呼び出されます。 layoutSubviewsの私のバージョンはすべてのビューでzオーダーを設定していたので、上記のtouchesBegan:withEventコードで設定していたzオーダーを元に戻していました。 AppleはbringSubviewToFrontのドキュメントにこの副作用について言及する必要があります。

UIViewサブクラスを使用する代わりに、CardLayerというサブクラスCALayerを作成しました。私は私のKlondikeViewサブクラスのタッチを以下のように扱います。 topZPositionは、すべてのカードの最も高い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

関連する問題