frame animation of uiimageView reduced - iphone

hie everyone, here is my code:
- (void)viewDidLoad {
[[UIAccelerometer sharedAccelerometer] setUpdateInterval:1.0/60.0];
[[UIAccelerometer sharedAccelerometer] setDelegate:self];
[super viewDidLoad];
}
-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
valueX = acceleration.x *20.0;
valueY = acceleration.y *-20.0;
int newX = (int)(imageView.center.x+valueX);
int newY = (int)(imageView.center.y+valueY);
CGPoint newCenter = CGPointMake(newX,newY);
imageView.center=newCenter;
UIImageView* imageView2 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"ball.png"]];
imageView2.frame = CGRectMake(newX-12, newY-12, 24, 24);
[self.view addSubview:imageView2];
[UIView beginAnimations:nil context:imageView2];
[UIView setAnimationDuration:10.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
imageView2.frame = CGRectMake(newX-2, newY-2, 4, 4);
[imageView2 setAlpha:0.0];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(removeSmoke:finished:context:)];
[UIView commitAnimations];
if(imageView2.alpha=0){
[imageView2 removeFromSuperview];
}
[self.view bringSubviewToFront:imageView];
}
At first my animation is very smooth with 1.0/60.0 but after some seconds the animation bug and is not smooth, i think it become 1.0/5.0. I don't know why . How can I solve this please ? sorry for my english I'm french :/

I'm not completely clear on what you are trying to achieve. It seems as though every time the accelerometer fires, you add in a new imageView animation, and want to move it based on some rules, as well shrink the image down. There are problems with your code though. You never call [imageView2 release];, and so you are probably getting memory problems after awhile.
You may also be doing too much computation in the method #selector(removeSmoke:finished:context:), but I'd need to see code in order to help with that.
If you know how many UIImageViews you are planning on having at one time, it is probably best to pre-load them, and put them in an array for easy access. That way, you can move one UIImageView, and move to the next one.
If you are shooting for iOS 4.0 or higher, I'd also recommend using Block Animations. They are easier to use, and I find a lot easier on the processor as well. Something like:
[UIView animateWithDuration:10.5
animations:^{
CGRect newRect = imageView2.frame;
newRect.origin.x -= newX-2;
newRect.origin.y -= newY-2;
imageView2.frame = newRect;
}
completion:^(BOOL finished){
[UIView animateWithDuration:0.1
animations:^{
// This is where you complete your animation, maybe remove from view or something?
}
completion:^(BOOL finished){
;
}];
}];
Finally, instead of adding and removing from the view, I would suggest you just setting the imageView2.hidden = YES;, and that way it won't get drawn, and has the same effect. Hope that helps!

Related

Oscillating UIView With Stopping Motion (iOS)

I need a view to enter the screen with oscillating animation and finally, the animation should stop in a natural way (decreasing oscillations - pendulum effect). I have added the subview above the screen so that the view rotates into the screen when required. The code for adding the subview is:
myView.layer.anchorPoint = CGPointMake(1.0, 0.0);
[[self view] addSubview:myView];
[myView setHidden:YES];
// Rotate 75 degrees to hide it off screen
CGAffineTransform rotationTransform = CGAffineTransformIdentity;
rotationTransform = CGAffineTransformRotate(rotationTransform, DEGREES_RADIANS(75));
bannerView.transform = rotationTransform;
bannerView.center = CGPointMake(((self.view.bounds.size.width)/2.0), -5.0);
[self performSelector:#selector(animateSwing) withObject:nil afterDelay:3.0];
The way I'm trying to achieve this that the view should rotate one full semi circle & back rotation, then rotate one semi circle rotation and finally come to halt at desired point using EaseOut animation curve. The code for my animateSwing() method is given below:
- (void)animateSwing {
NSLog(#"ANIMATING");
[myView setHidden:NO];
CGAffineTransform swingTransform = CGAffineTransformIdentity;
swingTransform = CGAffineTransformRotate(swingTransform, DEGREES_RADIANS(-20));
[UIView animateWithDuration:0.30
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
[UIView setAnimationRepeatCount:1.5];
[UIView setAnimationRepeatAutoreverses:YES];
myView.transform = swingTransform;
}completion:^(BOOL finished){
[UIView animateWithDuration:0.10
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
myView.transform = CGAffineTransformMakeRotation(DEGREES_RADIANS(0));
}completion:^(BOOL Finished){
}];
}];
}
For some reason the above code isn't working. If I do not chain animations, the code performs the semi-circle routine. But if I chain animations like above, it just oscillates a little bit around the desired point and ends abruptly.
Please suggest a fix to this code OR suggest a way to implement the required animation
Thanks
You want to use a keyframe animation. I actually have an example of a "decreasing waggle" animation in my book (http://www.apeth.com/iOSBook/ch17.html#_keyframe_animation):
CompassLayer* c = (CompassLayer*)self.compass.layer;
NSMutableArray* values = [NSMutableArray array];
[values addObject: #0.0f];
int direction = 1;
for (int i = 20; i < 60; i += 5, direction *= -1) { // alternate directions
[values addObject: #(direction*M_PI/(float)i)];
}
[values addObject: #0.0f];
CAKeyframeAnimation* anim =
[CAKeyframeAnimation animationWithKeyPath:#"transform"];
anim.values = values;
anim.additive = YES;
anim.valueFunction =
[CAValueFunction functionWithName: kCAValueFunctionRotateZ];
[c.arrow addAnimation:anim forKey:nil];
Of course that isn't identical to what you're trying to do, but it should get you started.

How can I animate zoom in / zoom out on iOS using Objective C?

I'm looking to replicate the zoom in / zoom out animations so common in iOS applications (example #1, #2). I am specifically looking for a source that can provide some common library with pre-specified values for ideal sort of animations. Like for zoom in, it should come with preconfigured transform values that are easily identifiable by human eye. Something like pop-animation and so on.
I assume these must be fairly well supported in iOS, either by a library or direct API support... But I'm not sure where to even start.
Use following code for zoom in and zoom out animation.
For Zoom In:
- (void)popUpZoomIn{
popUpView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.001, 0.001);
[UIView animateWithDuration:0.5
animations:^{
popUpView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1.0, 1.0);
} completion:^(BOOL finished) {
}];
}
For Zoom Out:
- (void)popZoomOut{
[UIView animateWithDuration:0.5
animations:^{
popUpView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.001, 0.001);
} completion:^(BOOL finished) {
popUpView.hidden = TRUE;
}];
}
Animations like that can be done without the need for 3rd party libraries.
Example:
self.frame = CGRectMake(0.0f, 0.0f, 200.0f, 150.0f);
[UIView beginAnimations:#"Zoom" context:NULL];
[UIView setAnimationDuration:0.5];
self.frame = CGRectMake(0.0f, 0.0f, 1024.0f, 768.0f);
[UIView commitAnimations];
Example Using Scale Also
UIButton *results = [[UIButton alloc] initWithFrame:CGRectMake(5, 5, 100, 100)];
[results addTarget:self action:#selector(validateUserInputs) forControlEvents:UIControlEventTouchDragInside];
[self.view addSubview:results];
results.alpha = 0.0f;
results.backgroundColor = [UIColor blueColor];
results.transform = CGAffineTransformMakeScale(0.1,0.1);
[UIView beginAnimations:#"fadeInNewView" context:NULL];
[UIView setAnimationDuration:1.0];
results.transform = CGAffineTransformMakeScale(1,1);
results.alpha = 1.0f;
[UIView commitAnimations];
source: http://madebymany.com/blog/simple-animations-on-ios
Applied on xCode 7 and iOS 9
//for zoom in
[UIView animateWithDuration:0.5f animations:^{
self.sendButton.transform = CGAffineTransformMakeScale(1.5, 1.5);
} completion:^(BOOL finished){
}];
// for zoom out
[UIView animateWithDuration:0.5f animations:^{
self.sendButton.transform = CGAffineTransformMakeScale(1, 1);
}completion:^(BOOL finished){}];
What I was looking for, considering the examples I gave, was a layer of abstraction that would give me most commonly used animation types.
Such types would enable the developer not only to include common animations like zoom in / zoom out, but also would incorporate optimum animation values (To, From, Timing etc.) so that developer doesn't have to worry about those.
I found one such library here, and I believe there are many more.

iphone development: how to create an animation by using NSTimer

In my app I have this code in viewWillAppear. It simply animates random object from top of the screen to the bottom. The problem is I need to detect collision and what I have learnt so far is it is impossible to retrieve the coordinates at any time for an animation. so how can I implement it by using NSTimer? or shall I use NSTimer? I could not figure it out. Any clue will be appreciated.
-(void)viewWillAppear:(BOOL)animated
{
for (int i = 0; i < 100; i++) {
p = arc4random_uniform(320)%4+1;
CGRect startFrame = CGRectMake(p*50, -50, 50, 50);
CGRect endFrame = CGRectMake(p*50, CGRectGetHeight(self.view.bounds) + 50,
50,
50);
animatedView = [[UIView alloc] initWithFrame:startFrame];
animatedView.backgroundColor = [UIColor redColor];
[self.view addSubview:animatedView];
[UIView animateWithDuration:2.f
delay:i * 0.5f
options:UIViewAnimationCurveLinear
animations:^{
animatedView.frame = endFrame;
} completion:^(BOOL finished) {
[animatedView removeFromSuperview];
}];
}
I would ditch NSTimer for CADisplayLink to send a message to your target. NSTimer can cause stuttering animations since it doesn't synchronize with the device's screen refresh rate. CADisplayLink does exactly that and makes your animations run like butter.
Documentation:
http://developer.apple.com/library/ios/#documentation/QuartzCore/Reference/CADisplayLink_ClassRef/Reference/Reference.html
Ultimately, using CADisplayLink looks something like this:
- (id) init {
// ...
CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:#selector(update:)];
[displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
// ...
}
- (void) update {
[myView updatePositionOrSomethingElse];
}
Your statement:
is it is impossible to retrieve the coordinates at any time for an
animation
seems incorrect did you check this?
It looks like you can use the CALayer's presentationLayer property to extract coordinates info during an animation:
CGRect movingFrame = [[yourView.layer presentationLayer] frame];
I will use this info to check time to time if there is a collision during the animation. So I will use the timer to check the collision status not for animating the views.
You can have your objects animate in small increments (in a loop may be). Every time you complete your animation, you can get the coordinates.
I think you could use the beginAnimations - commitAnimations syntax in a for cycle it could count for eg. till 10, so after each cycle you can check for collision
CGRect incrementedViewFrame;
for(int i = 0; i < 10; ++i)
{
incrementedViewFrame = CGRectMake(/*calculate the coords here*/);
if(collision)
{
//do stuff
}
else
{
//do an other animation cycle
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.1f];
[[self viewToAnimate]setFrame:incrementedViewFrame];
[UIView commitAnimations];
}
}
I hope that helps!

Animated moving UIButton not responding to touches/taps while moving

I'm trying to animate a UIButton to move up the screen. At any point the user can touch it. However, it doesn't seem to respond to touches while moving, only at the start and end of its animation. I guess this is because the button itself isn't moving, just the image of it. Any ideas how I can solve this? Here's my code so far. Thanks!
- (void)viewDidLoad {
[self newBubble];
[super viewDidLoad];
}
- (void)newBubble {
UIButton *bubble = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
bubble.frame = CGRectMake(10, 380, 50, 50);
UIImage *bubbleImage = [UIImage imageNamed:#"bubble.png"];
[bubble setBackgroundImage:bubbleImage forState:UIControlStateNormal];
bubble.imageView.contentMode = UIViewContentModeScaleAspectFit;
[bubble addTarget:self action:#selector(bubbleBurst:) forControlEvents:UIControlEventTouchDown];
[self.view addSubview:bubble];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:5.0];
CGAffineTransform newTransform = CGAffineTransformMakeScale(1.5, 1.5);
bubble.transform = CGAffineTransformTranslate(newTransform, 10, -200);
[UIView commitAnimations];
}
- (IBAction)bubbleBurst:(id)sender {
NSLog(#"Bubble burst");
UIButton *bubbleBurst = sender;
[bubbleBurst removeFromSuperview];
}
The +[UIView animateWithDuration:delay:options:animations:completion:] method takes a UIViewAnimationOptions argument. If you include UIViewAnimationOptionAllowUserInteraction, you should be able to press the button while it animates:
[UIView animateWithDuration:5.0
delay:0.0
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
CGAffineTransform newTransform = CGAffineTransformMakeScale(1.5, 1.5);
bubble.transform = CGAffineTransformTranslate(newTransform, 10, -200);
} completion:nil];
Well after posting a similar question, I found the answer here
Basically, you have to move the button frame by frame using an NSTimer. In my case I was worried there would be too many NSTimers involved moving each button, but in the end I used a single timer which loops through an array of buttons and moves them all one by one.
I'm pretty sure you would have to use Core Animation if you want the button to respond to touches while it is moving, but I have never done this so this is really more a tip then an answer!
I agree. I think the problem is that you're not using Core Animation. I can't believe you couldn't figure that out for yourself.

Any way of changing the duration of zoomToRect for UIScrollView?

Is there any way to specify a duration for the animation of [UIScrollView zoomToRect:zoomRect animated:YES]?
At the moment it's either fast animated:YES or instant animated:NO.
I'd like to specify a duration, eg [UIScrollView setAnimationDuration:2]; or something similar.
Thanks in advance!
Use the UIView's animations.
It's a bit long to explain, so I hope this little example will clear things up a bit.
Look at the documantation for further instructions
[UIView beginAnimations: nil context: NULL];
[UIView setAnimationDuration: 2];
[UIView setAnimationDelegate: self];
[UIView setAnimationDidStopSelector: #selector(revertToOriginalDidStop:finished:context:)];
expandedView.frame = prevFrame;
[UIView commitAnimations];
It's from a project I'm currently working on so it's a bit specific, but I hope you can see the basics.
I've had luck with this method in a UIScrollView subclass:
- (void)zoomToRect:(CGRect)rect duration:(NSTimeInterval)duration
{
[self setZoomLimitsForSize:rect.size];
if (duration > 0.0f) {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:duration];
}
[self zoomToRect:rect animated:NO];
if (duration > 0.0f)
[UIView commitAnimations];
[self zoomToRect:rect animated:(duration > 0.0f)];
}
It's kinda cheating, but it seems to mostly work. Occasionally it does fail, but I don't know why. In this case it just reverts to the default animation speed.
Actually these answers are really close to what I ended up using but I'll post mine separately since it is different. Basically the zoomToRect does not work correctly if the destination zoomScale is the same as the current one.
You could try to scrollToRect but I did not have any luck with that.
Instead just use the contentOffset and set it to the zoomRect.origin and nest that in the animation block.
[UIView animateWithDuration:duration
delay:0.f
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
if (sameZoomScale) {
CGFloat offsetX = zoomRect.origin.x * fitScale;
CGFloat offsetY = zoomRect.origin.y * fitScale;
[self.imageScrollView setContentOffset:CGPointMake(offsetX, offsetY)];
}
else {
[self.imageScrollView zoomToRect:zoomRect
animated:NO];
}
}
completion:nil];