UIView BringSubviewToFront:*不* 将视图带到前面 [英] UIView bringSubviewToFront: does *not* bring view to front

查看:20
本文介绍了UIView BringSubviewToFront:*不* 将视图带到前面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am implementing a simple iOS solitaire game that allows the user to drag the cards around in the usual way. The cards are represented with the UIView subclass CardView. All the card view's are siblings which are subviews of SolitaireView. The following snippet tries to "bring a card to the front" so that it is above all the other views as it is being dragged:

-(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-order 保持不变.在下面的图片中,我正在拖动国王.请注意它是如何正确地位于左图中的九个顶部,但在右侧图像中错误地位于两个下方(实际上是整个堆栈下方):

Unfortunately, the card's z-order remains unchanged during the drag. In the images below, I am dragging the King. Notice how it is correctly on top the Nine in the left image, but is incorrectly under the Two (under the entire stack actually) in the right image:

我也尝试更改 layer.zPosition 属性,但无济于事.如何在拖动过程中将卡片视图带到前面?我很困惑.

I also tried alter the layer.zPosition property as well to no avail. How can I bring the card view to the front during the drag? I am mystified.

推荐答案

已确认.bringSubviewToFront: 导致 layoutSubview 被调用.由于我的 layoutSubviews 版本在所有视图上设置了 z-orders,这会撤销我在上面的 touchesBegan:withEvent 代码中设置的 z-order.Apple 应该在 bringSubviewToFront 文档中提及这种副作用.

Confirmed. bringSubviewToFront: causes layoutSubview to be invoked. Since my version of layoutSubviews sets the z-orders on all the views, this was undoing the z-order I was setting in the touchesBegan:withEvent code above. Apple should mention this side effect in the bringSubviewToFront documentation.

我没有使用 UIView 子类,而是创建了一个名为 CardLayerCALayer 子类.我在我的 KlondikeView 子类中处理触摸,如下所示.topZPosition 是一个实例变量,用于跟踪所有卡片的最高 zPosition.请注意,修改 zPosition 通常是动画的——我在下面的代码中将其关闭:

Instead of using a UIView subclass, I created a CALayer subclass named CardLayer. I handle the touch in my KlondikeView subclass as listed below. topZPosition is an instance var that tracks the highest zPosition of all cards. Note that modifying the zPosition is usually animated -- I turn this off in the code below:

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

}

这篇关于UIView BringSubviewToFront:*不* 将视图带到前面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆