Drop image and release when it goes out of bounds - ios

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.

Related

animateWithDuration can't animating UIButton's bounds after UIButton has set an image

After I had set an image to an UIButton called bigIcon, I put it inside animateWithDuration with the change of its frame, then I ran the code, the button size changed instantly (has no animation), but it move from origin to destination slowly (has animation), how can I solve this problem? I found out that if I did set an image to the button this problem will disappear.
here is the code:
- (void)bigImage:(MCGodCell *)godCell withImage:(UIImage *)image {
self.bigIcon = [UIButton new];
self.bigIcon.adjustsImageWhenHighlighted = NO;
[self.bigIcon setBackgroundImage:image forState:UIControlStateNormal];
CGFloat iconX = self.tableView.frame.size.width / 2.0;
CGFloat iconY = self.tableView.frame.size.height / 2.0;
self.bigIcon.frame = CGRectMake(iconX, iconY, 1, 1);
[self.tableView addSubview:self.bigIcon];
CGFloat iconW = self.tableView.frame.size.width;
CGFloat iconH = iconW;
iconY = (self.view.frame.size.height - iconH) / 2.0;
[UIView animateWithDuration:0.3 animations:^{
self.bigIcon.frame = CGRectMake(0, iconY, iconW, iconH);
}];
}
You're not seeing the frame change because you're trying to animate it immediately after adding it to the view hierarchy.
UIKit needs to add the button as a subview, and then run the animation on the next UI update pass.
Wrap your animation block inside a dispatch_async block like this:
dispatch_async(dispatch_get_main_queue(), ^{
[UIView animateWithDuration:0.3 animations:^{
self.bigIcon.frame = CGRectMake(0, iconY, iconW, iconH);
}];
});

Permanently move a frame of custom UIView on screen

I'm having a little problem about animations on iOS with Objective-c.
I'm trying to create a card game, and as the game start, the deck distributes the cards on the table, with an animation. The problem is that at the beginning the cards are all in row in the bottom side of the screen, then with the animation they distribute all over the table. But when I tap on anyone of them, they return in their initial position, although the game keeps on working because they flip and unflip over, as well as the score works properly. I'm attaching some snippets of the code and of the view.
Here are links to screenshots:
1)cards as the game starts: prntscr.com/68r8yj
2)cards at the end of initial animation: prntscr.com/68r92u
3)cards as I tap on any of them: prntscr.com/68r2hr
Here's my code snippet
-(void)viewDidAppear:(BOOL)animated {
CGPoint startPoint = {21, 34};
for(int i = 0; i < [self.cardsView count]; i++) {
FrenchPlayingCardView *view = [self.cardsView objectAtIndex:i];
int width = view.bounds.size.width;
int height = view.bounds.size.height;
CGRect newFrame = CGRectMake(startPoint.x, startPoint.y, width, height);
/*[UIView animateWithDuration:1.0
delay:1.0
options:UIViewAnimationOptionTransitionNone
animations:^(){
view.frame = newFrame;;
}
completion:nil];*/
[UIView beginAnimations:#"move" context:nil];
[UIView setAnimationDuration:3.0];
view.frame = newFrame;
[UIView commitAnimations];
NSLog(#"index:%d %f %f", i, view.frame.origin.x, view.frame.origin.y);
startPoint.x += 76;
if(i % 4 == 3) {
startPoint.y += 100;
startPoint.x = 21;
}
}
[super viewDidAppear:animated];
}
call [super viewDidAppear] before your animation and close autolayout. I think autolayout can cause this

how to make smooth UIView splitting animation?

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];
}

UISnapBehaviour in x-axis only

Is there anyway to get UISnapBevahiour to only work along a linear x-axis?
I want the exact behaviour of a UISnapBehaviour but don't want it to 'shake' into position on both x & y axis, just the x axis.
This is for a UIView inside my contentView of a table cell.
// UIKitDynamics
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self];
CGPoint centerPoint = self.contentView.center;
self.snapBehaviour = [[UISnapBehavior alloc] initWithItem:self.frontView snapToPoint:centerPoint];
[self.snapBehaviour setDamping:1.0f];
[self.animator addBehavior:self.snapBehaviour];
UIDynamicItemBehavior *itemBehaviour = [[UIDynamicItemBehavior alloc] initWithItems:#[self.frontView]];
itemBehaviour.elasticity = 0.0f;
itemBehaviour.allowsRotation = NO;
[self.animator addBehavior:itemBehaviour];
From UIDynamicBehavior documentation of it's action block:
#property(nonatomic, copy) void (^action)(void)
The dynamic animator calls the action block on every animation step.
So when creating your behaviour, do something like this:
UIView *view = ...
UIAttachmentBehavior *attachment = [[UIAttachmentBehavior alloc] initWithItem:view attachedToAnchor:point];
CGFloat xCoordinate = view.frame.origin.x;
attachment.action = ^{
if (view.frame.origin.x != xCoordinate) {
CGRect frame = view.frame;
frame.origin.x = xCoordinate;
view.frame = frame;
}
};
[self.dynamicAnimator addBehavior:attachment];
In my example I use a UIAttachmentBehavior but this method will also work for any other subclass of UIDynamicBehavior, in your case a UISnapBehavior.
I'll post the code I used to do a similar thing, as I mentioned in my comment it used UIView animation that leverage UIKit Dynamics underneath as opposed to using them directly...
[UIView animateWithDuration:0.5
delay:0.0
usingSpringWithDamping:0.5
initialSpringVelocity:0.3
options:UIViewAnimationOptionCurveEaseIn
animations:^{
[toView setFrame:_modalFrame];
}
completion:^(BOOL finished) {
[self.context completeTransition:YES];
}];
This presents modal view which springs up and oscillates a bit on presentation.

UIView animationWithDuration recursive cause jitter

I tried to set the property as atomic but it doesn't seems to work anyway. Here's the code. It move a label displaying the song name being played. And sometime it start jittering as if the label was supposed to be at two places at the same time. Any clue ? Some lock property maybe...
- (void)animateSongLabel
{
if (!self.player.rate) {
[UIView animateWithDuration:.5 animations:^{
self.songLabel.left = 25.f;
}];
return;
}
[UIView animateWithDuration:.25 delay:0. options:UIViewAnimationOptionCurveLinear animations:^{
self.songLabel.left -= 15.f;
} completion:^(BOOL finished) {
if (self.songLabel.right < -10.f) {
self.songLabel.left = 320.f;
}
[self animateSongLabel];
}];
}
The rock-bottom simplest way to make text that just sits there and scrolls sideways is to display an animated UIImage or animated UIImageView - especially the former, because it animates forever, which is probably what you want. Generate the successive UIImage objects in code by drawing your text slightly offset each time, and hand them to animatedImageWithImages:duration:. Now wherever you show that image, it will be animating.
Here's some sample code to get you started (tweak to get precisely the effect you have in mind):
NSString* s = #"Mister Dobbalena, Mister Bob Dobbalena";
NSMutableArray* marr = [NSMutableArray array];
UIFont* f = [UIFont fontWithName:#"Helvetica" size:12];
float w = [s sizeWithFont:f].width;
for (int offset = 0; offset < w; offset++) {
UIGraphicsBeginImageContextWithOptions(self.iv.frame.size, NO, 0);
[s drawAtPoint:CGPointMake(10-offset,20) withFont:f];
[marr addObject: UIGraphicsGetImageFromCurrentImageContext()];
UIGraphicsEndImageContext();
}
UIImage* im = [UIImage animatedImageWithImages:marr duration:20];
self.iv.image = im;

Resources