UIView带来SubviewToFront:确实*不*将视图带到前面
我正在实施一个简单的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]; ... } }
不幸的是,卡的z顺序在拖动期间保持不变。 在下面的图片中,我拖着国王。 请注意它在左图像中的九个顶部是正确的,但在右图像中的两个(实际上在整个堆栈下)不正确:
我也试过改变layer.zPosition
属性也无济于事。 如何在拖动过程中将卡片视图置于正面? 我很神秘。
证实。 bringSubviewToFront:
导致调用layoutSubview
。 由于我的layoutSubviews
版本在所有视图上设置了z顺序,因此撤消了我在上面的touchesBegan:withEvent
代码中设置的z顺序。 Apple应该在bringSubviewToFront
文档中提到这种副作用。
我创建了一个名为CardLayer
的CALayer
子类,而不是使用UIView
子类。 我在下面列出的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]; //... } // ... } }