我正在实现一个简单的 iOS 单人纸牌游戏,允许用户以通常的方式拖动纸牌。卡片由 UIView
子类 CardView
表示。所有卡片 View 都是兄弟 View ,它们是 SolitaireView
的 subview 。以下代码片段尝试“将卡片置于最前面”,以便它在被拖动时位于所有其他 View 之上:
-(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
属性,但无济于事。
如何在拖动过程中将卡片 View 置于最前面?我很困惑。
最佳答案
确认。 bringSubviewToFront:
导致调用 layoutSubview
。由于我的 layoutSubviews
版本在所有 View 上设置了 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];
//...
}
// ...
}
}
关于ios - UIView bringSubviewToFront : does *not* bring view to front,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10019130/