UIView带来SubviewToFront:确实*不*将视图带到前面

wco*_*ran 7 uiview uitouch ios

我正在实现一个简单的iOS纸牌游戏,允许用户以通常的方式拖动卡片.这些卡用UIView子类表示CardView.所有卡片视图都是兄弟姐妹,是子视图SolitaireView.以下代码片段尝试"将卡片放在前面",以便在拖动时它位于所有其他视图上方:

-(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];
      ...
   }
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,卡片的z顺序在拖动过程中保持不变.在下面的图片中,我拖着国王.请注意它在左图像中的九个顶部是正确的,但在右图像中的两个(实际上在整个堆栈下)不正确:

在此输入图像描述 在此输入图像描述

我也试过改变layer.zPosition房产也无济于事.如何在拖动过程中将卡片视图置于正面?我很神秘.

wco*_*ran 8

证实.bringSubviewToFront:导致layoutSubview被调用.由于我的版本layoutSubviews在所有视图上设置了z顺序,因此撤消了我在touchesBegan:withEvent上面的代码中设置的z顺序.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];
        //...                                                                                                            
     }
     // ...                                                                                                             
   }

}
Run Code Online (Sandbox Code Playgroud)

  • 我认为使用'UIView`用于扑克牌可能是一个糟糕的设计选择 - 我认为它们并不是真的用于此.我想我会退后一步,用"CALayer"代替. (4认同)