Move UIImageView from A to B - ios

I need to move an UIImageView from x,y to x,y1.
This is what i have. I tried lots of different codes in -(void)animation, most using animateWithDuration but none seems to work. It just doesn't do anything. I must be missing something. Is .h correct? How would you make the image move? I then have to loop that, how can i do that? It's my first time with animate, I can't figure out what to do, it has to be simple. Thanks in Advance.
in .h I connected it this way
#import <UIKit/UIKit.h>
#interface ImageBeaconViewController : UIViewController {
__weak IBOutlet UIImageView *blueView;
}
#end
the in .m I've got
- (void)viewDidLoad
{
[self animation];
[super viewDidLoad];
}
....
- (void)animation{
[UIView animateWithDuration:3 animations:^{
blueView.alpha = 1;
blueView.center = CGPointMake(blueView.center.x , blueView.center.y +??);
}];
}
??= I still have to decide how much I want it to move
This way the app crashes as soon as I get to the screen with the animation

Add Method Like This:
- (void) animateToPoint:(CGPoint)point {
[UIView animateWithDuration:3 animations:^{
blueView.alpha = 1;
blueView.center = point;
}];
}
Call like this:
- (void) viewDidAppear:(BOOL)animated {
int distanceToSlide = 40; // will slide down 40px (use -40 to go up)
CGPoint targetPoint = CGPointMake(blueView.center.x, blueView.center.y + distanceToSlide);
[self animateToPoint:targetPoint];
}
NOTE
Notice that I put your animation call in viewDidAppear if you animate in viewDidLoad you won't see anything because your view isn't displayed yet.
If it's still not moving, make sure "useAutolayout" is not selected check this:
Just because I already built it, try this for tap to animate:
In your viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc]init];
tap.numberOfTapsRequired = 1;
[tap addTarget:self action:#selector(handleTap:)];
[self.view addGestureRecognizer:tap];
}
Then, use these:
- (void) handleTap:(UITapGestureRecognizer *)tap {
int distanceToSlide = 40; // will slide down 40px (use -40 to go up)
CGPoint targetPoint = CGPointMake(blueView.center.x, blueView.center.y + distanceToSlide);
[self animateToPoint:targetPoint];
}
- (void) animateToPoint:(CGPoint)point {
[UIView animateWithDuration:3 animations:^{
blueView.alpha = 1;
blueView.center = point;
}];
}
Here's a way to loop it:
#implementation ImageBeaconViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
pointA = CGPointMake(40, 40);
pointB = CGPointMake(250, 350);
blueView.center = pointA;
}
- (void) viewDidAppear:(BOOL)animated {
[self animate];
}
- (void) animate {
if (CGPointEqualToPoint(_blueView.center, pointA)) {
[self animateToPoint:pointB];
}
else {
[self animateToPoint:pointA];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void) animateToPoint:(CGPoint)point {
[UIView animateWithDuration:1.0 animations:^{
_blueView.alpha = 1;
_blueView.center = point;
} completion:^(BOOL finished) {
if (finished) {
[self animate];
}
}];
}
#end

[UIView animateWithDuration:0.3 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
blueView.alpha = 1;
blueView.center = CGPointMake(blueView.center.x , blueView.center.y + 100);
} completion:^(BOOL finished) {
//if you need any thing after animation is done
}];
this is them code for animation i have

Related

Animating a UITextview in a UIToolbar issue

I am trying to animate a UITextView to expand the to the width of its containing UIToolbar.
But it animates weird, jumping around.
Can anyone help me make understand why my textbox jumps around?
#define ANIMATION_DURATION 0.5
#define ANIMATION_DELAY 0.03
#interface WebViewController () <UITextFieldDelegate>{
CGRect URLBAR_DEFAULT;
}
-(void)viewDidLoad{
self.txtURLBar = [[UITextField alloc] init];
self.txtURLBar.bounds = CGRectMake(0, 0, 100, 30);
self.txtURLBar.delegate = self;
self.txtURLBar.backgroundColor = [UIColor lightGrayColor];
self.txtURLBar.clearButtonMode = UITextFieldViewModeWhileEditing;
URLBAR_DEFAULT = self.txtURLBar.frame; //KEEP A REFRENCE TO THE ORIGINAL SIZE
}
//START EDITING EXPAND TO FULL WIDTH
- (void)textFieldDidBeginEditing:(UITextField *)textField {
[UIView animateWithDuration:ANIMATION_DURATION delay:ANIMATION_DELAY options:UIViewAnimationOptionCurveLinear animations:^{
[_txtURLBar setFrame:CGRectMake(3, URLBAR_DEFAULT.origin.y, self.view.frame.size.width - 10, URLBAR_DEFAULT.size.height)];
} completion:^(BOOL finished) {
}];
}
//END EDITING SHRINK BACK TO SMALL SIZE
- (void)textFieldDidEndEditing:(UITextField *)textField {
[UIView animateWithDuration:ANIMATION_DURATION delay:ANIMATION_DELAY options:UIViewAnimationOptionCurveEaseOut animations:^{
[_txtURLBar setFrame:CGRectMake(URLBAR_DEFAULT.origin.x, URLBAR_DEFAULT.origin.y, URLBAR_DEFAULT.size.width, URLBAR_DEFAULT.size.height)];
} completion:^(BOOL finished) {
}];
}
The problem may be due to the frame being set in textFieldDidBeginEditing, textFieldDidEndEditing is different. I've done the small POC with same code of yours as below. It's working fine.
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UITextField *resizeableTextField;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//START EDITING EXPAND TO FULL WIDTH
- (void)textFieldDidBeginEditing:(UITextField *)textField {
[UIView animateWithDuration:0.5 delay:0.03 options:UIViewAnimationOptionCurveLinear animations:^{
self.resizeableTextField.frame = CGRectMake(CGRectGetMinX(self.resizeableTextField.frame), CGRectGetMinY(self.resizeableTextField.frame), self.resizeableTextField.frame.size.width + 40, CGRectGetHeight(self.resizeableTextField.frame));
} completion:^(BOOL finished) {
}];
}
//END EDITING SHRINK BACK TO SMALL SIZE
- (void)textFieldDidEndEditing:(UITextField *)textField {
[UIView animateWithDuration:0.5 delay:0.03 options:UIViewAnimationOptionCurveEaseOut animations:^{
self.resizeableTextField.frame = CGRectMake(CGRectGetMinX(self.resizeableTextField.frame), CGRectGetMinY(self.resizeableTextField.frame), self.resizeableTextField.frame.size.width - 40, CGRectGetHeight(self.resizeableTextField.frame));
} completion:^(BOOL finished) {
}];
}
#end

iOS Frameworks needed for animation

I have a simple animation to fade out an image but it is not working. The method is being called but no animation. What frameworks are required in the project for this? Think that might be the issue since the image just goes right to alpha:0 with no animation.
#import "TutorialViewController.h"
#interface TutorialViewController ()
#end
#implementation TutorialViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self popupImage];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)popupImage
{
NSLog(#"It worked");
_imageView.hidden = NO;
_imageView.alpha = 1.0f;
// Then fades it away after 2 seconds (the cross-fade animation will take 0.5s)
[UIView animateWithDuration:1
delay:2
options:UIViewAnimationOptionCurveEaseIn
animations:^{
_imageView.alpha = .0f;
}
completion:^(BOOL finished) {
// Once the animation is completed and the alpha has gone to 0.0, hide the view for good
_imageView.hidden = NO;
}];
}

Perform a Segue after animation but animated items get back to their previous position

I have this problem, i have set in the Storyboard 2 UIButton and after touching one of them they must move, so i implemented this using animation, and works fine. But after the completion of the animation i'm performing a modal segue, the problem is that while modal segue is starting, raising the new UIView from the bottom, the 2 UIButton return to their previous place, where i set them in the Storyboard, and it's orribile to see. How could i solve this?
Here's the code i'm using
#property (strong, nonatomic) IBOutlet UIButton *maleBtn;
#property (strong, nonatomic) IBOutlet UIButton *femaleBtn;
- (void)viewDidLoad
{
[super viewDidLoad];
[_maleBtn addTarget:self
action:#selector(chooseGender:)
forControlEvents:UIControlEventTouchUpInside];
[_femaleBtn addTarget:self
action:#selector(chooseGender:)
forControlEvents:UIControlEventTouchUpInside];
}
- (IBAction)chooseGender:(id)sender
{
CGRect maleFrame;
CGRect femaleFrame;
if (sender == _maleBtn) {
maleFrame = self.maleBtn.frame;
maleFrame.origin.x = (self.view.bounds.size.width/2) - 15;
femaleFrame = self.femaleBtn.frame;
femaleFrame.origin.x = self.view.bounds.size.height;
}
else {
maleFrame = self.maleBtn.frame;
maleFrame.origin.x = -self.view.bounds.size.height;
femaleFrame = self.femaleBtn.frame;
femaleFrame.origin.x = (self.view.bounds.size.width/2) - 15;
}
[UIView animateWithDuration:0.5
delay:0.5
options:UIViewAnimationCurveEaseOut
animations:^{
_maleBtn.frame = maleFrame;
_femaleBtn.frame = femaleFrame;
}
completion:^(BOOL finished){
if(sender == _maleBtn)
[self performSegueWithIdentifier:#"toMale" sender:self];
else
[self performSegueWithIdentifier:#"toFemale" sender:self];
}];
}
At the top you make a bool or add a property in your .h if you like. But I would just use a local variable for this.
BOOL didAnimate;
In viewDidLoad you set it
- (void)viewDidLoad
{
[super viewDidLoad];
//Set the bool value here to no;
didAnimate = NO;
[_maleBtn addTarget:self
action:#selector(chooseGender:)
forControlEvents:UIControlEventTouchUpInside];
[_femaleBtn addTarget:self
action:#selector(chooseGender:)
forControlEvents:UIControlEventTouchUpInside];
}
Use it here, and I also took the liberty to rewrite your code a bit.
- (IBAction)chooseGender:(id)sender
{
CGRect maleFrame;
CGRect femaleFrame;
if (sender == _maleBtn) {
maleFrame = self.maleBtn.frame;
maleFrame.origin.x = (self.view.bounds.size.width/2) - 15;
femaleFrame = self.femaleBtn.frame;
femaleFrame.origin.x = self.view.bounds.size.height;
}
else {
maleFrame = self.maleBtn.frame;
maleFrame.origin.x = -self.view.bounds.size.height;
femaleFrame = self.femaleBtn.frame;
femaleFrame.origin.x = (self.view.bounds.size.width/2) - 15;
}
[UIView animateWithDuration:0.5
delay:0.5
options:UIViewAnimationCurveEaseOut
animations:^{
_maleBtn.frame = maleFrame;
_femaleBtn.frame = femaleFrame;
}
completion:^(BOOL finished){
didAnimate = YES;
}];
if(sender == _maleBtn && didAnimate){
[self performSegueWithIdentifier:#"toMale" sender:self];
}
else if((sender == _femaleBtn && didAnimate)){
[self performSegueWithIdentifier:#"toFemale" sender:self];
}
else{
NSLog(#"failure to transition");
}
}
I have not tested this and there might be spelling errors and such. So copy/paste might not work.

How to recognize tapping on the whole oscillating SubView to perform interactive animation

In the code below, the subview (cloud) oscillates on the location given.
On tapping that subview while oscillation, it moves out of the bounds to the right side, then moves in from the left.
But the tap gesture is not working on the whole subview, it works only on the right-side end of the oscillating subView.
I want slide out and in of cloud to work, whenever the whole subview of cloud is tapped.
Below is code of .h and .m file respectively.
File : OscillatingCloudsViewController.h
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#interface OscillatingCloudsViewController : UIViewController
{
IBOutlet UIView *movingCloud1;
UIImage *cldImg;
}
- (IBAction)animateCloud;
- (IBAction)animateCloudBegin;
#end
File : OscillatingCloudsViewController.m
#import "OscillatingCloudsViewController.h"
#implementation OscillatingCloudsViewController
- (void) viewWillAppear:(BOOL)animated
{
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapGestureAnimateCloud)];
tapGesture.numberOfTapsRequired = 1;
tapGesture.numberOfTouchesRequired = 1;
tapGesture.cancelsTouchesInView = YES;
[movingCloud1 addGestureRecognizer:tapGesture];
movingCloud1.userInteractionEnabled = YES;
[super viewWillAppear:
animated];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self animateCloud];
}
- (IBAction) animateCloud
{
cldImg = [UIImage imageNamed:#"cloud1.png"];
movingCloud1=[[UIView alloc]initWithFrame:CGRectMake(50, 50, cldImg.size.width, cldImg.size.height)];
[movingCloud1 setBackgroundColor:[UIColor colorWithPatternImage:cldImg]];
[self.view addSubview:movingCloud1];
movingCloud1.userInteractionEnabled = YES;
[self viewWillAppear:YES];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:5];
[UIView setAnimationRepeatCount:HUGE_VALF];
[UIView setAnimationRepeatAutoreverses:YES];
CGPoint pos = movingCloud1.center;
pos.x = 220.0f;
movingCloud1.center = pos;
[UIView commitAnimations];
}
- (void) animateCloudHidden
{
[movingCloud1 setHidden:YES];
}
- (IBAction)animateCloudBegin
{
movingCloud1.frame = CGRectMake(-100, 50, cldImg.size.width, cldImg.size.height);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1];
[UIView setAnimationRepeatCount:1];
[UIView setAnimationRepeatAutoreverses:NO];
CGPoint pos = movingCloud1.center;
pos.x = cldImg.size.width;
movingCloud1.center = pos;
[UIView commitAnimations];
}
- (IBAction) tapGestureAnimateCloud
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:2];
[UIView setAnimationRepeatCount:1];
[UIView setAnimationRepeatAutoreverses:NO];
movingCloud1.center = CGPointMake(1100.0f, 81.5f);
[UIView commitAnimations];
[self performSelector:#selector(animateCloudBegin) withObject:nil afterDelay:2.0f];
[self performSelector:#selector(animateCloudHidden) withObject:nil afterDelay:3.0f];
[self performSelector:#selector(animateCloud) withObject:nil afterDelay:3.0f];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
I have understood your problem. In viewwillApper you are assing the Gesture and in inside animateCloud method your allocating your movingCloud1 UIView.
For implementing this you need to fallow the bello steps.
In ViewdidLoad you need to allocate and add the movingCloud1 view to you self.view.
After add the Gesture to movingCloud1 view.
Your tapGesture will work now. So inside your tapgesture method just you need to set the animation for your movingCloud1 view

Second touch animation

Trying to get to grips with Xcode and seem to be making some progress over the last few weeks.
Does anyone know a way that a custom button can do a different set of animations on a second click.
So let say I have a custom button and its of Mario, when i click it he runs from the middle of the screen and out of the right hand side of the screen and then runs back in to the middle from the left of the screen, he also makes noise.
I have achieved this using this code:
- (IBAction)marioRunning_clicked:(id)sender
{
[UIView animateWithDuration:1.50 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
marioRunning.center = CGPointMake(350.5, 456.0);
} completion:^(BOOL finished) {
if (finished) {
[UIView animateWithDuration:0.00 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
marioRunning.center = CGPointMake(-30.5, 456.0);
} completion:^(BOOL finished) {
if (finished) {
[UIView animateWithDuration:1.50 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
marioRunning.center = CGPointMake(160.0, 456.0);
} completion:^(BOOL finished) {
if(finished) // NSLog ( #"Finished !!!!!" );
marioRunning.center = CGPointMake(160.0, 456.0);
}];
}
}];
}
}];
marioRunning.imageView.animationImages = [NSArray arrayWithObjects:[UIImage imageNamed:#"mario-running2"],[UIImage imageNamed:#"mario-running3"],nil];
marioRunning.imageView.animationDuration = 0.15;
marioRunning.imageView.animationRepeatCount = 19;
[marioRunning.imageView startAnimating];
}
How could I make him do a second set of animations on the next click? For example instead of running from left to right, if i tap him the second time he will Jump up and down?
Use the selected state of the button to decide which animation to do
-(void)buttonClicked:(UIButton*)button
{
if(button.selected)
{
[self doAnimation1];
}
else
{
[self doAnimation2];
}
button.selected = !button.selected;
}
This might be overkill, but here's a cool way to do what you want:
Make a subclass of UIButton, and let's call it DDDMarioButton:
typedef void (^DDDAnimationBlock)(UIButton *button);
#interface DDDMarioButton : UIButton
- (void)addAnimationBlockToQueue:(DDDAnimationBlock)block;
#end
Then in DDDMarioButton.m:
#interface DDDMarioButton ()
#property (nonatomic, strong) NSMutableArray *animationQueue;
#end
#implementation DDDMarioButton
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
}
return self;
}
- (void)buttonPressed:(id)button
{
DDDAnimationBlock block = self.animationQueue[0];
block(self);
[self.animationQueue removeObjectAtIndex:0];
}
- (void)addAnimationBlockToQueue:(DDDAnimationBlock)block
{
if(!self.animationQueue)
{
self.animationQueue = [NSMutableArray new];
}
[self.animationQueue addObject:block];
}
#end
and then wherever you create your buttons, you add each step one by one:
DDDMarioButton *button = [[DDDMarioButton alloc] initWithFrame:CGRectZero];
[button addAnimationBlockToQueue:^(UIButton *button) {
// perform some animation
}];
[button addAnimationBlockToQueue:^(UIButton *button) {
// perform another animation
}];
And that should do it. I haven't tested this, you'll probably need some configuration, but that's pretty much the idea.

Resources