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];
...
}
}
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:
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.
Just one single method will let you to bring your view to the front and the magic words are : myView. bringToFront(); “.
The UIView class is a concrete class that you can instantiate and use to display a fixed background color. You can also subclass it to draw more sophisticated content.
Creating Custom Views programatically Open Xcode ▸ File ▸ New ▸ File ▸ Cocoa Touch class ▸ Add your class name ▸ Select UIView or subclass of UIView under Subclass of ▸ Select language ▸ Next ▸ Select target ▸ Create the source file under your project directory.
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.
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];
//...
}
// ...
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With