Archive for July 2014
UICollectionViewCell Flip and Move
In my previous post I asked how to both flip and move a UIView. My co-worker Jason Hanson found that adding a “container” view and moving that while flipping the child view worked great. So the example code now looks like this:
[UIViewtransitionWithView:self.flipView
duration:5.0
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
self.containerView.frame = CGRectOffset(self.containerView.frame, 0, –250);
self.flipView.backgroundColor = [UIColor redColor];
} completion:^(BOOL finished) {
self.isFlipViewUp = NO;
}];
With that solved, I could move on to implementing the bigger picture effect I was working on – flipping a UICollectionViewCell, centering it in the window with a modal type background, then flipping it back.
I love this effect, and I’m proud of my code. But I’m wondering if there is a better way to do it.
To demonstrate I created a little sample project that flips a playing card:
The initial flip needs to:
1. Flip the card from its back to its face
2. Add a gray overlay to the rest of the visible screen
3. Center the card on the screen
Here’s the code:
– (void)flipCard
{
// grap the screen size and create a view with the same frame
// set its background to clear so it can be animated
UIWindow *mainWindow = [[[UIApplicationsharedApplication] delegate] window];
self.modalView = [[UIView alloc] initWithFrame:mainWindow.frame];
self.modalView.backgroundColor = [UIColorclearColor];
[mainWindow addSubview:self.modalView];
// remove the tapToPresentCardGesture
// then add the tapToHideCardGesture both to the cell and the modal view
[self.contentView removeGestureRecognizer:self.tapToPresentCardGesture];
[self.contentView addGestureRecognizer:self.tapToHideCardGesture];
[self.modalView addGestureRecognizer:self.tapToHideCardGesture];
// translate the frame of the cell to the main window
self.originalFrame = self.frame;
CGPoint translatedOrigin = [self convertPoint:self.bounds.origin toView:self.modalView];
self.translatedFrame = CGRectMake(translatedOrigin.x, translatedOrigin.y, self.frame.size.width, self.frame.size.height);
self.frame = self.translatedFrame;
// add the cell to the modalView
[self.modalView addSubview:self];
// flip the contentView while repositioning the actual cell view
[UIViewtransitionWithView:self.contentView
duration:0.5
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
// animate the backgroundColor of the modalView to a semi-transparent black
self.modalView.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.75];
// move the cell to the center of the screen
self.center = mainWindow.center;
// change the imageView to the card image
[self.cardImageView setImage:[UIImage imageNamed:@”AC”]];
} completion:nil];
}
When it flips back it needs to:
1. Flip the card from its face to its back
2. Remove the gray overlay
3. Replace the card back into the UICollectionView
Here’s that code:
– (void)hideCard
{
// flip the contentView back from right to left
[UIViewtransitionWithView:self.contentView
duration:0.5
options:UIViewAnimationOptionTransitionFlipFromRight
animations:^{
// animate the backgroundColor of the modalView to clear
self.modalView.backgroundColor = [UIColor clearColor];
// animate the cell back to its original spot
self.frame = self.translatedFrame;
// set its image back to “Back”
[self.cardImageView setImage:[UIImage imageNamed:@”Back”]];
} completion:^(BOOL finished) {
// remove the modalView along with its tapGesture and set it to nil
[self.modalView removeFromSuperview];
[self.modalView removeGestureRecognizer:self.tapToHideCardGesture];
self.modalView = nil;
// reset the tap on the contentView to show the card
[self.contentView removeGestureRecognizer:self.tapToHideCardGesture];
[self.contentView addGestureRecognizer:self.tapToPresentCardGesture];
// tell the delegate that the cell is back
[self.delegate cardDidHide];
}];
}
Notice that it calls a delegate. The delegate is the UICollectionView which simply calls reloadData to get the cell back:
– (void)cardDidHide
{
// when the cell comes back it needs to be added back to this view
// calling reloadData will do this correctly
[self.collectionView reloadData];
};
Is this the simplest way of doing this? Could I do this better?
Flip and Move a UIView – What Am I Doing Wrong?
This is definitely a newbie question but I figure I’ll post it here then ask Twitter people for the answer cause its Monday and I’m feeling lazy.
I want to use UIView transitionWithView:duration:options:animations:completion: to flip a UIView and reposition it. The problem I’m having is that the first half of the animation has a clipped view. The second half works as expected.
Here’s the code:
– (void)viewDidLoad
{
[superviewDidLoad];
UITapGestureRecognizer *tapFlipView = [[UITapGestureRecognizeralloc] initWithTarget:selfaction:@selector(flip)];
[self.flipView addGestureRecognizer:tapFlipView];
self.flipView.backgroundColor = [UIColorredColor];
self.isFlipViewUp = YES;
}
– (void)flip
{
if( self.isFlipViewUp )
{
[UIViewtransitionWithView:self.flipView
duration:5.0
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
self.flipView.frame = CGRectOffset(self.flipView.frame, 0, 250);
} completion:^(BOOL finished) {
self.isFlipViewUp = NO;
}];
}
else
{
[UIViewtransitionWithView:self.flipView
duration:5.0
options:UIViewAnimationOptionTransitionFlipFromRight
animations:^{
self.flipView.frame = CGRectOffset(self.flipView.frame, 0, –250);
} completion:^(BOOL finished) {
self.isFlipViewUp = YES;
}];
}
}
The result of this code looks like this:
What am I doing wrong?