I am trying to animate the dealing of cards. Currently I have two cards, the dealer card (dCard1) and the player card (pCard1).
The player card should be dealt and as soon as it is dealt, the dealer card should then be dealt.
What is currently happening is the player card will animate properly when I press the deal button, but instead of waiting till the player card is done animating, the dealer card just appears at the dealerTo location. It does not animate. I am new to doing animations any help would be greatly appreciated.
-(void) animateHandsDealt: (Hand*) pHand:(Hand*) dHand{
pCard1= [[UIImageView alloc] initWithFrame:CGRectMake(125, 0, 75, 110)];
dCard1= [[UIImageView alloc] initWithFrame:CGRectMake(125, 0, 75, 110)];
CGFloat start = 0;
CGFloat duration = 1;
CGPoint playerTo = CGPointMake(120, 300);
CGPoint dealerTo = CGPointMake(120, 70);
pCard1.image = [UIImage imageNamed:[[pHand.cardArr objectAtIndex:0 ] imagePath]];
[self.view addSubview: pCard1];
[playerImages addObject:pCard1];
CABasicAnimation *move = [CABasicAnimation animationWithKeyPath:#"position" ];
move.fillMode = kCAFillModeBoth;
move.beginTime = start;
[move setToValue:[NSValue valueWithCGPoint:playerTo]];
[move setDuration:duration];
move.removedOnCompletion = FALSE;
[[pCard1 layer] addAnimation:move forKey:#"position"];
dCard1.image = [UIImage imageNamed:#"back-red-75-1.png"];
[self.view addSubview: dCard1];
CABasicAnimation *move2 = [CABasicAnimation animationWithKeyPath:#"position" ];
[move2 setToValue:[NSValue valueWithCGPoint:dealerTo]];
move2.beginTime = start + duration;
[move2 setDuration:duration];
move2.fillMode = kCAFillModeBoth;
move2.removedOnCompletion = FALSE;
[[dCard1 layer] addAnimation:move2 forKey:#"position"];
}
If you're just animating the frame of the view, you can use the much simpler UIView animateWithDuration... methods.
You chain them by using the animateWithDuration:animations:completion: version. You can specify the second animation in the completion: block of the first animation.
http://developer.apple.com/library/ios/#documentation/uikit/reference/uiview_class/UIView/UIView.html#//apple_ref/doc/uid/TP40006816-CH3-SW109
I don't have access to your classes (of course), but I think this is pretty close to "drop-in-ready" code. What do you think?
- (void)deal {
// Of course, you'd replace these NSString objects with actual card objects...
NSArray *array = [NSArray arrayWithObjects:#"pCard1", #"dCard1", #"pCard2", #"dCard2", #"pCard3", #"dCard3", nil];
[self performSelectorOnMainThread:#selector(animateDealWithArray:) withObject:array waitUntilDone:YES];
}
- (void)animateDealWithArray:(NSArray *)array {
// constants that won't change call to call
static CGFloat duration = 1;
static CGSize cardSize = {75, 110};
static CGPoint playerTo = {120, 300};
static CGPoint dealerTo = {120, 70};
// Seems like you want the card to start at the top of the "deck" whether it's a player card or not
UIImageView *card = [[UIImageView alloc] initWithFrame:CGRectMake(125, 0, 75, 110)];
// Figure out if the first object (the one we're currently using) is a player or dealer card
if ([[array objectAtIndex:0] isKindOfClass:[PlayerCard Class]]) {
// Player card, so show the "face"
[card setImage:[UIImage imageNamed:[(PlayerCard *)[array objectAtIndex:0] imagePath]]];
[UIView animateWithDuration:duration
animations:^{
[card setFrame:CGRectMake(playerTo.x, playerTo.y, cardSize.width, cardSize.height)];
}
completion:^(BOOL finished) {
[self dealNext:array];
}
];
} else {
// Dealer card, so show the back
[card setImage:[UIImage imageNamed:#"back-red-75-1.png"]];
[UIView animateWithDuration:duration
animations:^{
[card setFrame:CGRectMake(dealerTo.x, dealerTo.y, cardSize.width, cardSize.height)];
}
completion:^(BOOL finished) {
[self dealNext:array];
}
];
}
}
- (void)dealNext:(NSArray *)array {
int count = [array count];
if (count > 1) {
NSArray *newArray = [array subarrayWithRange:NSMakeRange(1, count - 1)];
[self animateDealWithArray:newArray];
}
}
Related
In my code, I have an area on which when users taps and holds, UILongPressGestureRecognizer causes an animation to run and at the end of animation a method gets called.
(It's basically a long tap on a small area square which contains one CGPoint so that it starts a long press animation and when it finishes, the point is removed.)
The problem: On iPhone 5s,SE and 6, UILongPressGestureRecognizer works fine but on any device released after that, it gets dismissed very quickly and I have tried it on at least 11 different devices.
Why is that?!
I appreciate any help.
-(void)prepareLongPressGesture{
_longGesture = [[UILongPressGestureRecognizer alloc]
initWithTarget:self
action:#selector(handleLongGesture:)];
_longGesture.delegate = self;
_longGesture.allowableMovement = self.frame.size.width*0.15;
_longGesture.minimumPressDuration = 1.0;
[self addGestureRecognizer:_longGesture];
}
- (void)handleLongGesture:(UILongPressGestureRecognizer*)gesture {
switch (gesture.state) {
case UIGestureRecognizerStateBegan:
[self removeModifiablePoint];
break;
case UIGestureRecognizerStateChanged:
case UIGestureRecognizerStateEnded:
case UIGestureRecognizerStateCancelled: {
if (self.animatedView.superview) {
[self.animatedView removeFromSuperview];
}
} break;
default:
break;
}
}
- (void)removeModifiablePoint {
CGFloat sizeOFLongPressAnimation = 0.0;
if (IS_IPAD) {
sizeOFLongPressAnimation = 0.15*self.frame.size.width;
}else{
sizeOFLongPressAnimation = 0.27*self.frame.size.width;
}
if (!_animatedView) {
self.animatedView =
[[UIView alloc] initWithFrame:CGRectMake(0, 0, sizeOFLongPressAnimation, sizeOFLongPressAnimation)];
self.animatedView.alpha = 0.7f;
self.animatedView.layer.borderColor = [UIColor redColor].CGColor;
self.animatedView.layer.borderWidth = 3.f;
self.animatedView.layer.cornerRadius = sizeOFLongPressAnimation / 2.0f;
self.progressView = [[UIView alloc] initWithFrame:self.animatedView.bounds];
self.progressView.backgroundColor = [UIColor redColor];
self.progressView.layer.cornerRadius = sizeOFLongPressAnimation / 2.0f;
[self.animatedView addSubview:self.progressView];
}
CGPoint center = [self.modifiablePointsArray[_modifiablePointIndex] CGPointValue];
self.animatedView.center = center;
[self addSubview:self.animatedView];
self.progressView.transform =
CGAffineTransformScale(CGAffineTransformIdentity, 0.1, 0.1f);
[UIView animateWithDuration:2.f animations:^{
self.progressView.transform = CGAffineTransformIdentity;
}completion:^(BOOL finished) {
if (finished) {
[self.animatedView removeFromSuperview];
[self.modifiablePointsArray removeObjectAtIndex:_modifiablePointIndex];
[self setNeedsDisplay];
}
}];
}
I am new to programming in Objective-C, and am currently having an issue with the code below. I am trying to make an image drop when a button is touched, and it simply freezes when trying to do so. It needs to drop the image until it reaches the bottom of the screen, which then it should be released.
- (IBAction)itemDrop:(UIButton *)sender{
if (strncmp([[sender currentTitle] UTF8String], [copyPrimaryArray[0] UTF8String], 2) == 0)
{
UIImage *bubblImage = [UIImage imageNamed:#"Red_apple.png"];
UIImageView *appleImg = [[UIImageView alloc] initWithImage:bubblImage];
appleImg.translatesAutoresizingMaskIntoConstraints = NO;
[appleImg setContentMode:UIViewContentModeScaleAspectFit];
[appleImg sizeToFit];
[self.view addSubview:appleImg];
NSLog(#"You clicked the Apple");
int i = 0;
CGPoint coordinates = sender.frame.origin;
CGFloat x = coordinates.x;
CGFloat y = coordinates.y;
CGFloat z = UIScreen.mainScreen.bounds.size.height;
while (y < z) {
[UIView beginAnimations:nil context:nil];
appleImg.center = CGPointMake(x, y+i);
[UIView commitAnimations];
i++;
}
}
}
You do not need to move the image view one point at a time manually. That's what I seem to understand from your use of the while loop. Objective-c does a lot of things for you.
UIImage *bubblImage = [UIImage imageNamed:#"Red_apple.png"];
UIImageView *appleImg = [[UIImageView alloc] initWithImage:bubblImage];
// Set the frame of the original position here, for example:
CGRect originalPosition = CGRectMake(0, 0, appleImg.frame.size.width, appleImg.frame.size.height);
appleImg.frame = originalPosition;
// Then animate it to the new position:
[UIView animateWithDuration:1.0
animations:^{
CGRect newPosition = CGRectMake(0, 640, appleImg.frame.size.width, appleImg.frame.size.height);
appleImg.frame = newPosition;
}
completion:^(BOOL finished) {
NSLog(#"completion block"); // You can set the completion block to nil if you have nothing to do here.
}];
Make sure to start using block based animations.
The use of UIView's beginAnimations:context is highly discouraged since iOS 4.0.
Hi i am trying to implement split the UIView using UIPinchGestureRecognizer, but the following issue are their, if any one know how to solve kindly.
This is my pinchGestureHandlerCode:
- (IBAction)splitView:(UIPinchGestureRecognizer*)recognizer
{
if(recognizer.state == UIGestureRecognizerStateBegan)
{
CGPoint selectedFolderPoint = CGPointMake([recognizer locationInView:recognizer.view].x,
recognizer.view.frame.origin.y);
self.splitPosition = ([recognizer locationOfTouch:0 inView:recognizer.view].x +
[recognizer locationOfTouch:1 inView:recognizer.view].x)/2;
//STEP 1: Capture the Main View Content into an image
[self captureImageFromPointAndSetupMaskView:selectedFolderPoint];
}
else if(recognizer.state == UIGestureRecognizerStateChanged)
{
CGPoint selectedFolderPoint = CGPointMake(recognizer.scale,
recognizer.view.frame.origin.y);
//STEP 2: Reduce the left image width, and move the right image origin according to the finger move of user.
[self layoutBottomPartOfMainViewRelativeToPointInMainView:selectedFolderPoint];
[UIView beginAnimations:#"split" context:NULL];
[UIView setAnimationDuration:0.1];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
//captures the main background view's image
//STEP 3- Push The Layer-3 which hosts the other part of the Main Content View
[UIView commitAnimations];
}
else if(recognizer.state == UIGestureRecognizerStateEnded)
{
// STEP 3: remove the both image view from the view.
[self layoutFinalFrameOfBottomPartOfMainContentView];
[UIView commitAnimations];
}
}
STEMP 1 METHOD:
-(void)captureImageFromPointAndSetupMaskView:(CGPoint)selectedFolderPoint
{
UIGraphicsBeginImageContext(self.superview.frame.size);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *backgroundImage = UIGraphicsGetImageFromCurrentImageContext();
CGImageRef leftTempRef = backgroundImage.CGImage;
CGImageRef leftImageRef = CGImageCreateWithImageInRect(leftTempRef,
CGRectMake(self.bounds.origin.x,
self.bounds.origin.y, selectedFolderPoint.x,
self.bounds.size.height));
UIImage *leftImage = [UIImage imageWithCGImage:leftImageRef];
leftImageBackgroundView = [[UIImageView alloc] initWithImage:leftImage];
[self.leftBackgroundView addSubview:leftImageBackgroundView];
CGImageRef rightTempRef = backgroundImage.CGImage;
CGImageRef rightImageRef = CGImageCreateWithImageInRect(rightTempRef,
CGRectMake(selectedFolderPoint.x,
self.bounds.origin.y, self.superview.bounds.size.width, self.bounds.size.height));
UIImage *rightImage = [UIImage imageWithCGImage:rightImageRef];
rightImageBackgroundView = [[UIImageView alloc] initWithImage:rightImage];
[self.rightBackgroundView addSubview:rightImageBackgroundView];
[self.leftBackgroundView setFrame:CGRectMake(self.bounds.origin.x,
self.bounds.origin.y,
selectedFolderPoint.x,
self.frame.size.height)];
[self.rightBackgroundView setFrame:CGRectMake(selectedFolderPoint.x,
self.bounds.origin.y,
self.superview.bounds.size.width,
self.bounds.size.height)];
}
STEP 2 METHOD:
-(void)layoutBottomPartOfMainViewRelativeToPointInMainView:(CGPoint)selectedFolderPoint
{
[self.leftBackgroundView setFrame:CGRectMake(self.leftBackgroundView.bounds.origin.x,
self.leftBackgroundView.bounds.origin.y,
(self.leftBackgroundView.bounds.size.width -
selectedFolderPoint.x),
self.leftBackgroundView.bounds.size.height)];
[self.rightBackgroundView setFrame:CGRectMake(self.rightBackgroundView.frame.origin.x + selectedFolderPoint.x,
self.rightBackgroundView.bounds.origin.y,
self.rightBackgroundView.bounds.size.width - selectedFolderPoint.x,
self.rightBackgroundView.bounds.size.height)];
if(((ABS(self.leftBackgroundView.bounds.origin.x+self.leftBackgroundView.bounds.size.width)-
self.rightBackgroundView.bounds.origin.x) > 100) &&
((ABS(self.leftBackgroundView.bounds.origin.x+self.leftBackgroundView.bounds.size.width)-
self.rightBackgroundView.bounds.origin.x) < 110))
{
[self switchView];
NSDictionary *message;
[self.timelineController sendEvent:SWITCH_VIEW withMessage:message];
[self layoutFinalFrameOfBottomPartOfMainContentView];
}
[UIView setAnimationsEnabled:NO];
[UIView setAnimationsEnabled:YES];
}
STEP 3 METHOD:
-(void)layoutFinalFrameOfBottomPartOfMainContentView
{
[self.leftBackgroundView setFrame:CGRectMake(self.bounds.origin.x,
self.leftBackgroundView.bounds.origin.y,
self.bounds.origin.x,
self.leftBackgroundView.bounds.size.height)];
[self.rightBackgroundView setFrame:CGRectMake(self.bounds.origin.x,
self.rightBackgroundView.bounds.origin.y,
self.bounds.origin.x,
self.rightBackgroundView.bounds.size.height)];
leftImageBackgroundView.image = nil;
rightImageBackgroundView.image = nil;
}
The issue are:
i am trying to make smooth animation but its running too fast and suddenly moving both side.
if i to same pinch gesture more number of time app getting crash and showing memory warning.
if any one know what mistake i am doing in my code kindly help me to solve the problem or there is any other way to do the same animation kindly give way to me....
Thanks in advance... ...
Define the UIPinchGestureRecognizer like this
UIPinchGestureRecognizer *ges = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(split)];
[self addGestureRecognizer:ges];
and the split Method like this
- (void)split {
CGRect f = self.frame;
CGRect f1 = CGRectMake(CGRectGetMinX(f), f.origin.y, f.size.width/2, f.size.height);
CGRect f2 = CGRectMake(CGRectGetMidX(f), f.origin.y, f.size.width/2, f.size.height);
SplitView *view1 = [[[SplitView alloc] initWithFrame:f1] autorelease];
[self.superview addSubview:view1];
SplitView *view2 = [[[SplitView alloc] initWithFrame:f2] autorelease];
[self.superview addSubview:view2];
f1.origin.x -= 30;
f2.origin.x += 30;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
view1.frame = f1;
view2.frame = f2;
[UIView commitAnimations];
[self removeFromSuperview];
}
i Have requirement were i have to animate image view from current position to full screen in grid view. i made images into Grid view.
- (void)viewDidLoad
{
[super viewDidLoad];
imagesArray = [[NSMutableArray alloc] init];
for (int i=1; i<11; i++) {
[imagesArray addObject:[UIImage imageNamed:[NSString stringWithFormat:#"image%d.png", i]]];
NSLog(#"imagesArray:%#", imagesArray);
}
float horizontal = 20.0;
float vertical = 20.0;
for(int i=0; i<[imagesArray count]; i++)
{
if((i%3) == 0 && i!=0)
{
horizontal = 20.0;
vertical = vertical + 220.00 + 20.0;
}
imagesView = [[UIImageView alloc] initWithFrame:CGRectMake(horizontal, vertical, 310.0, 220.00)];
imagesView.userInteractionEnabled = YES;
[imagesView setImage:[imagesArray objectAtIndex:i]];
imagesView.tag = i;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
tap.numberOfTapsRequired = 1;
tap.numberOfTouchesRequired = 1;
[imagesView addGestureRecognizer:tap];
[self.view addSubview:imagesView];
horizontal = horizontal + 310.0 + 20.0;
}
}
here i have created grid view with images, like i have 10 images. i made 3x3 grid view.
next i have add tap gesture to it and i am getting the image view position by calling with tag
-(void)handleTap:(UITapGestureRecognizer *)recognizer
{
UIView *piece = recognizer.view;
[UIView animateWithDuration:1.0 animations:^{
piece.frame = CGRectMake(piece.frame.origin.x, piece.frame.origin.y, 1000, 700);
} completion:^(BOOL finished) {
}];
}
Can you say me how to make image view animate from current position to full screen by tapping on it.
Since you're adding the views to self.view of your view controller, you can assume that self.view is occupying the entire screen of the device. Therefore, you can animate to its bounds:
[UIView animateWithDuration:1.0 animations:^{
piece.frame = self.view.bounds;
} completion:nil];
Note that if piece must have a parent view that spans across the entire screen so that your inner view won't be clipped during animation.
This code will help u to add the animation effect like zoom your imageview that your are expecting. You need to customize once the animation is over show the full screen image view.
-(void)addZoomAnimationToZoomViewController:(UIImageView *)zoomView
{
CABasicAnimation *zoomAnimation = [CABasicAnimation animationWithKeyPath:#"transform.scale"];
[zoomAnimation setDuration:0.8];
[zoomAnimation setRepeatCount:1];
[zoomAnimation setFromValue: [NSNumber numberWithFloat:0.1]];
[zoomAnimation setToValue: [NSNumber numberWithFloat:5.0] ];
[zoomAnimation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[[zoomView layer] addAnimation:zoomAnimation forKey:#"zoom"];
}
I am coding a custom transition based on the Shutter transition tutorial. it's pretty simple, the first view controller is meant to divide into hundreds of pieces and then fade one at a time, problem however is that it doesn't work in landscape mode. apparently the "contentsRect" method of CALayer (which is supposed to work on the normalized image space) only works in the portrait mode. I have attached my file in here if anyone needs to have a look and please if you can help me.
http://tinyurl.com/88669oy
regards
here is also my trans code:
CALayer* viewLayer;
- (void)transitWithImageView:(UIImageView *)imgView inView:(UIView *)view withImage:(UIImage *)img
{
viewLayer = [imgView layer];
[view.layer addSublayer:viewLayer];
CGSize layerSize = viewLayer.bounds.size;
// BEGINING OF MAKE ARRAY OF TRANSITIONS
NSMutableArray* allTransitionsArr = [[NSMutableArray alloc] init];
for ( int i = 0; i < BLOCK_COUNT; i++ )
{
CABasicAnimation *fade = [CABasicAnimation animationWithKeyPath:#"opacity"];
fade.toValue = [NSNumber numberWithFloat:-1-sqrt(i)];
fade.autoreverses = NO;
fade.duration = DURATION;
[allTransitionsArr addObject: fade];
}
// END OF MAKE ARRAY OF TRANSITIONS
NSMutableArray *blocks = [[NSMutableArray alloc] init];
[viewLayer removeFromSuperlayer];
[CATransaction begin];
[CATransaction setCompletionBlock:^(void)
{
[blocks enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
{
[obj setDelegate:nil];
[obj removeFromSuperlayer];
}];
[view.layer addSublayer:viewLayer];
}];
CGFloat bandWidth = layerSize.width / sqrt(BLOCK_COUNT);
CGFloat bandHeight = layerSize.height / sqrt(BLOCK_COUNT);
int yVal = -1;
for(int i = 0; i < BLOCK_COUNT; i++)
{
CALayer *block = [[CALayer alloc] init];
block.masksToBounds = YES;
CGFloat xOffset = 1.f / sqrt(BLOCK_COUNT);
CGFloat yOffset = 1.f / sqrt(BLOCK_COUNT);
block.bounds = CGRectMake(0, 0, bandWidth, bandHeight);
block.bounds = CGRectMake(0.f, 0.f, bandWidth, bandHeight);
block.contents = (id)[img CGImage];
block.contentsGravity = kCAGravityCenter;
CGPoint bandOrigin = viewLayer.frame.origin;
bandOrigin.x = bandOrigin.x + (bandWidth * (i % (int)sqrt(BLOCK_COUNT)));
if (i % (int)sqrt(BLOCK_COUNT) == 0 )
yVal++;
bandOrigin.y = bandOrigin.y + (bandHeight * yVal);
// PROBLEM IS GOT TO BE HERE
block.contentsRect = CGRectMake(xOffset * (i % (int)sqrt(BLOCK_COUNT)) ,yOffset * yVal, xOffset, yOffset);
[block setValue:[NSValue valueWithCGPoint:bandOrigin] forKeyPath:#"frame.origin"];
[view.layer addSublayer:block];
[block addAnimation:[allTransitionsArr objectAtIndex: BLOCK_COUNT - i - 1] forKey:nil];
[blocks addObject:block];
[block release];
}
[CATransaction commit];
[blocks release];
}