UIView bringSubviewToFront: *不*将视图带到前面

Posted

技术标签:

【中文标题】UIView bringSubviewToFront: *不*将视图带到前面【英文标题】:UIView bringSubviewToFront: does *not* bring view to front 【发布时间】:2012-04-04 20:57:53 【问题描述】:

我正在实现一个简单的 ios 纸牌游戏,它允许用户以通常的方式拖动卡片。卡片用UIView 子类CardView 表示。所有卡片视图都是兄弟姐妹,它们是SolitaireView 的子视图。以下 sn-p 尝试“将卡片放在前面”,以便在拖动时它高于所有其他视图:

-(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 属性也无济于事。 如何在拖动过程中将卡片视图置于前面?我很困惑。

【问题讨论】:

我发现bringSubviewToFront: 触发了要设置视图的“needsLayout”标志。我的 layoutSubviews 方法也调用了 bringSubviewToFront: 从而将所有视图 z 顺序恢复到初始状态! 那有什么解决办法呢?我也有同样的要求,从卡片列表中,如果我选择任何中间顺序卡片,它应该出现,然后来到前面。但我的动画由于bringSubviewToFront: 方法而无法正常工作 如果您坚持使用 UIView 子类,那么您需要标记正在拖动的卡片,以便 layoutSubviews 可以将其放在顶部。我实际上改用了下面提到的 CALayers。 感谢您的回复。你能把代码放上去吗? 下面列出了一个代码sn-p。 【参考方案1】:

已确认。 bringSubviewToFront: 导致调用 layoutSubview。由于我的layoutSubviews 版本在所有视图上都设置了z 顺序,这将撤消我在上面的touchesBegan:withEvent 代码中设置的z 顺序。 Apple 应在 bringSubviewToFront 文档中提及此副作用。

我没有使用UIView 子类,而是创建了一个名为CardLayerCALayer 子类。我在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];
        //...                                                                                                            
     
     // ...                                                                                                             
   


【讨论】:

我认为将UIView 用于扑克牌可能是一个糟糕的设计选择——我不认为它们真的是为此而设计的。我想我会退后一步,改用CALayer

以上是关于UIView bringSubviewToFront: *不*将视图带到前面的主要内容,如果未能解决你的问题,请参考以下文章

在 UIView2 上方显示 UIView1,但在 UIView1 上方显示 UIView2 输入方式

统计从多个 UIView 中随机抽出的 UIView 数量,即:从 9 个 UIView 中随机抽出 5 个 UIView,然后执行操作

UIView 类别 - 自定义方法不返回 UIView

IOS将UIVIew中的UIImageView扁平化为单个UIView [重复]

UIView - 啥覆盖将允许更新 UIView 框架

UIView 中的 UIView 问题