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
子类,而是创建了一个名为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];
//...
// ...
【讨论】:
我认为将UIView
用于扑克牌可能是一个糟糕的设计选择——我不认为它们真的是为此而设计的。我想我会退后一步,改用CALayer
。以上是关于UIView bringSubviewToFront: *不*将视图带到前面的主要内容,如果未能解决你的问题,请参考以下文章
在 UIView2 上方显示 UIView1,但在 UIView1 上方显示 UIView2 输入方式
统计从多个 UIView 中随机抽出的 UIView 数量,即:从 9 个 UIView 中随机抽出 5 个 UIView,然后执行操作