in ios dev, how to handle case based animations? - iphone

My questions is probably best asked by stating my problem:
In my app, there are two button choices, lets say 1 & 2. when you click and hold on 1, 2 fades out (alpha change) over .3 seconds, and vice versa.
If the user 'cancel's' that button touch (by dragging his finger away from the button and releasing) the opposite button fades back in.
This all works great. The problem arises when the user does not hold down on the button, and clicks it so a touch is registered in under .3 seconds (the time it takes for the other button to fade out) The thing is there are more animations that have to happen after all this so i guess my issue is that animations further down the line interrupt that .3 sec fade and things start to look awkward.
Suggestions to work with this? Thank you!

As suggested in this post, you should create a secondary UIView animation that goes to the same animation endpoint as your 0.3 second one. Make sure you set the animation to begin from the current state, and give it as short as time as it will let you. Basically this will get your views to all look like they would at the end of that first animation, and it will happen much more quickly. After that animation is done, you would do your other animations based on the button results.
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.03];
[UIView setAnimationCurve: UIViewAnimationCurveLinear];
// here you set your view and animation stuff from the other animation that takes 0.3 seconds
[UIView commitAnimations];
This will get you quickly to the state you would be in after the 0.3 second animation and you can begin the animation from there.

Related

Core Animation and UIImageView returning to starting position

I have a UIImageView that I'm moving across the screen based on a user swiping. I accomplish this using Core Animation:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
movingView.frame = theRect;
[UIView commitAnimations];
It always starts out fine, but partway through going from its original location to the "theRect" location, it stops and the UIImageView jumps back to its starting point. It's never at the same point. Sometimes gets almost all the way through before jumping back, sometimes only barely moving then jumping back. No other code is running after this. I've tried changing the duration and it doesn't seem to matter.
If I add in:
[UIView setAnimationDidStopSelector:#selector(completeAnimation:finished:context:)];
[UIView setAnimationDelegate:self];
Then it actually delays until the Duration is complete and runs the selector, even if the image itself stops and returns to its starting point almost immediately.
Hopefully someone can give me some hints at what might be going on here.
If using autolayout, you can animate the changing of the constraint, not animating the change of the frame (because when constraints are reapplied, the original location will be restored). See Animating an image view to slide upwards for an example.

sliding bar in iOS, like facebook when losing network connection

I need to provide a sliding bar in iOS to alert the user that he entered wrong data.
I want it to appear for about 1 second at the top of the screen and then disappear, so something with animcation and commit. but I couldn't find any good documentation for this.
Any ideas?
Thanks.
First you need an imageView of your notification bar or a button to be animating, which is yourObject.
With this method you put the banner on screen (change coordinates to whatever suites you) Also if you want it flip down as Apple has some of their notifications you can use the rotation, if not just delete that line.
//yourObject setHidden to NO
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:.5];
self.yourObject.center = CGPointMake(100, 200);
self.yourObject.transform = CGAffineTransformMakeRotation(0);
[UIView commitAnimations];
Next just make a timer which after 1 second invokes some method to do the opposite of the one I have posted.
if you want a very simple appear and disappear instead of sliding you can replace the two lines before commitAnimations with
yourObject.alpha=1

Fade in Fade out button menu

I want to make a 'menu' with 4 options. This has to be 1 big frame where the buttons are being faded in and faded out over time, 1 by 1.
So only 1 button is visible at any given time , not 4;
These buttons ofcourse are filled with Images
I don't know how to start , i've checked out some photoalbum code but it hasn't helped me.
The main problem is the user can click at any time in the animation of fade in and fade out, so how to decide when to go where ?
Because when one imagebutton is faded out 50% another is 50% faded in.
try something like this....
[UIView beginAnimations:nil context:self.view];
[UIView setAnimationDuration:1];
[yourButton setImage:[UIImage imageNamed:your-image-name] forState:UIControlStateNormal];
[UIView commitAnimations];
if you dont want that the user can click during an animation then just disable (UIControl is inherited by UIButton) the buttons during animation.
You can set the UIView-Animation-Delegate to your class so your class gets notified when animation starts, ends, ...
[UIView setAnimationDelegate]
edit: if you want that the user can click on buttons during animation you have to know the wanted behaviour: which buttons should be clickable at which time?

I want to animate, in fact fade, "within" drawRect

Is there a way to make drawRect animate FROM THE PREVIOUS SCENE to the next one?
(Amazingly) you can animate inside drawRect - try it. You can fade, translate or animate any other property.
However, it starts "from fresh", from blank. So for example if you put a fade-in animation block in drawRect, the previous scene with disappear and the new scene will fade up from white.
I want the screen to fade from the previous image (drawn in the previous cycle of drawRect) to the new image I have just drawn ... err, am drawing.
Is there a way to do that, perhaps trickily by manipulating what's going on with drawRect?
This would seem to be a very common use case - blending from one scene to the next.
Does anyone know the secret?
Of course, obviously this can be done in the core animation milieu or in many other ways, but having drawRect fade from one drawRect to the next is an obvious idea. Cheers.
Astounding update thanks to the genius of WrightCS.....
Thanks only to WrightCS, we now know that drawRect handles animations perfectly. Simply paste this code at the end of any drawRect and try it:
self.alpha = 0.0;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:2];
self.alpha = 1.0;
[UIView commitAnimations];
it treats the entire drawRect, no matter how complex, as one enormous block and it wraps it in that animation. Yes, it even includes painted in offscreen areas, bitmap rendering or anything else. Everything gets animated. Who knew?
The problem at hand - how to make it start the animation from the previous scene rather than start from blank?
Drawrect Is invisible. It happens in the 'backbuffer' which the iOS displays on screen only when you're ready with drawRect. So you can definitely not animate while in drawrect. However, you can commit animation instrucions from just about anywhere, including drawrect. But the animation will be performed afterwards.
Animation requires timing and showing different frames to the user.
You CAN do that all by yourself (constantly forcing a redraw and doing something slightly different in drawrect each the time) but that's a lot of work, especialy if you want it done right.
Luckily iOS has many animation effects programmed for you. Either using Core Animation, or the (more simple and basic) animation in UIKit. But since it works by animating certain properties of views (eg the alpha of a whole view, or the rotation of a whole view, ...) you might need to rearrange your views and subviews to make good use of it.
E.g. Each horse limb is separate subview and you animate their transformations (no redraw needed, iOS will do the rest)
E.g. The old and new frame are two separate views and you animate the new frame (which is on top) from alpha 0 to alpha 1.
You can animate the alpha:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:2.0];
myObject.alpha = 0.0;
[UIView commitAnimations];
if you are under iOS 5.0+, you can use the following:
...
[UIView animateWithDuration:0.3
delay:0.0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{
//do your stuff here
}completion:^(BOOL finished) {
//completition stuff go here
}];
...
The best thing you can do is to use two UIView instances and animate between them.
When you are starting the animation you have to know which is the original and final state of the animation. That's difficult if it's only one view.

How to make a dragging UIView decelerating?

I have a UIView that can be dragged with the finger which I've implemented by using a UIPanGestureRecognizer. This allows me to drag a view horizontally ; left or right.
I make my view moving while receiving the following state from the UIPanGestureRecognizer (using the translationInView: method):
UIGestureRecognizerStateBegan
UIGestureRecognizerStateChanged
What happens for now, is the view stops moving as soon as the finger leaves the surface of the screen, which renders a non natural effect.
What I would like, would be that the dragging view decelerates starting from the state UIGestureRecognizerStateEnded by stopping smoothly.
Such a behavior is used by UIScrollView class and subclasses (UIWebView, UITableView, etc.).
I've tried severals approaches by calculating from the velocity, the time the touch occurred and stopped a stop distance, etc. But honestly I have a feeling of going nowhere to get a natural behavior. I even tried to use physics engine like Chipmunk. But I find this to complicated for what I try to achieve, and I'm pretty sure there should be a better (if not easier) solution.
Thanks a lot!
Jérémy
In your gesture recognizer, make it so that when your finger leaves the screen, you begin an animation to continue to scroll a bit, for a short duration, with an "Ease Out" transition.
Maybe something like:
[UIView beginAnimations:#"FingerOff" context:nil];
[UIView setAnimationDuration:0.25f];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDelegate:self];
[UIView setAnimationCurve:UIAnimationViewEaseOut];
[myView setFrame:newFrame];
[UIView commitAnimation];
You can substitute setFrame to something else - whatever establishes how you want to scroll or view - maybe even a setCenter. Make it a scroll a bit "further" than the current position.