emulate bounce effect in iphone app without UIScrollView - iphone

I am using a pan gesture to drag an item in my app. I know I could use a UIScrollView to get that "bounce" effect when dragging to an edge. However, that seems like a hack, so I'd like to find a way to get that effect when manually dragging an item (setting its frame or center point). I'm curious if there's a standard way, or a physics library in the Accelerate framework, something like that which wouldn't require me implementing my own physics engine.

The standard UIView animation curve is one that uses the accelerate / decelerate curve, which should gives a nice "bounce back" action.
It's really easy to use. Once you decide you want to "snap back" to a location, do this:
[UIView beginAnimations:nil context:nil];
CGRect newFrame = viewToAnimate.frame;
newFrame.origin.x = snapBackXcoordinate;
viewToAnimate.frame = newFrame;
[UIView commitAnimations];
to entirely emulate the UIScrollView you'll also need to set a "maximum stretch" distance before you stop stretching more.
But why re-invent the wheel? The UIKit components you're given are there to use. If putting your view into a UIScrollView does the trick, go ahead and use it. Saves you develop and debug time.

Related

iPhone How to get photo taken effect like in camera application?

I am talking about that effect when user presses button to take photo, it shrinks and moves to toolbar? How is this achieved in general?
You can create this by both scaling (applying a transform) and moving (animating the position) of the image.
I wrote about a similar animation (the Open in Background animation from Safari on iPhone) in this blog post. Not all of the code is necessary but some part of it will be useful for the animation you are trying to do.
You should
Calculate the scale factor to make the image the appropriate size
Calculate the path you want to animate the image along.
Animate a scale with the calculated scale factor
Animate a position animation along the path (using a CAKeyframeAnimation)
Since you are doing two animations at once you could benefit from using a CAAnimationGroup.
Since you are animating down to a toolbar which probably is another part of the view hierarchy than where the image is you may need to use method like
- (CGRect)convertRect:(CGRect)rect toView:(UIView *)view
and
- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view
To translate coordinates between the different views.
so the shrink animation is achived by
[UIView beginAnimations:#"animationShrink" context:NULL];
[UIView setAnimationDuration:kSlideInAnimationDuration];
flipFlopContainer.transform = CGAffineTransformMakeScale(0.01, 0.01);
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(shrinkAnimationFinished:)];
[UIView commitAnimations];
after this animation in shrinkAnimationFinished method you need to define a path to follow and change the position of your view accroding to that path.
See the following thread for that animation
Resize and move a UIView with Core Animation (CAKeyFrameAnimation)

UIScrollView not calling layoutSubviews while zooming on iOS 4.0

I've read many of the UIScrollView questions asked on here but none of them answered this problem.
I have a UIScrollView that zooms a view containing other subviews. When a zoom is happening, I need to have the subviews of the view move to certain places. I can accomplish this by changing their frames accordingly in the layoutSubviews method of the UIScrollView.
On iOS 3.2 and lower, this works great both for finger-zooming and pragmatic zooming using zoomToRect:animated: method.
On iOS 4.0 or higher, this only works great for finger-zooming. With pragmatic zooming using zoomToRect:animated:, a call to layoutSubviews only happens once (at the end of the zoom). I need this method to get called many times during the duration of the zoom so that my subviews can have smooth position changes along with the zoom.
So in summary, on iOS 3.2, a call to layoutSubviews happens many times and on iOS 4.0 a call to layoutSubviews happens only once when you call zoomToRect:animated:. Does anyone know of a solution to my problem?
In IOS 4.0, animations are done by the OS - I assume to make use of GPU based hardware acceleration as much as possible. As a disadvantage of that, it becomes harder to animate a values that is derived from another (animated) value. As in your case, the positions of the subviews that depend on the zoom level of the UIScrollView.
In order to make that happen, you should setup the animation of the subviews to go in parallel with the animation of the zooming. Try something like:
[UIView animateWithDuration:0.5 delay:0
options:UIViewAnimationOptionLayoutSubviews
animations:^{
theScrollView.zoomScale = zoomScale;
[theScrollView layoutSubViews];
} completion:^(BOOL finished) {}];
This should set the frame properties of the subviews from within the same animation context, and therefore, they should be animated together by the OS.
I am not sure whether the explicit layoutSubViews is needed, or whether the UIViewAnimationOptionLayoutSubviews option already achieves that.
See also the answers to this question: How to make UIScrollView send scrollViewDidScroll messages during animations

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.

UITextField editing issue - iPhone SDK

I am having an issue with my UITextFields in my iPhone app that I am hoping someone here may have seen before.
I have a few UITextField's on my screen, and when they are tapped and they keyboard appears they are covered. To overcome this, I animated the view to move up with:
-(void)moveViewUpFromValue:(float)fromOldValue toNewValue:(float)toNewValue keep:(BOOL)keep {
CABasicAnimation *theAnimation;
theAnimation=[CABasicAnimation animationWithKeyPath:#"transform.translation.y"];
theAnimation.duration=0.25;
theAnimation.repeatCount=1;
if(keep) {
[theAnimation setRemovedOnCompletion:NO];
[theAnimation setFillMode:kCAFillModeForwards];
}
theAnimation.fromValue=[NSNumber numberWithFloat:fromOldValue];
theAnimation.toValue=[NSNumber numberWithFloat:toNewValue];
[self.view.layer addAnimation:theAnimation forKey:#"animateLayer"];
}
This, visually, works great, however, when I go to edit (hold the screen down to get the magnifying glass), it doesn't appear. The interaction are is retained in the position before it moves.
Any ideas what could be going on here?
Many thanks,
Brett
This is an interesting way to animate such a thing, but not the most common one.
You're actually animating a transformation of a view - not the actual position of the view. Appearantly the magnifying glass doesn't obey the transformation (quite logical, for it would sheer, stretch and skew with the view otherwise).
So rather animate the position, i.e. self.view.frame or self.view.center (which boils down to the same thing). Furthermore I usually use [UIView beginAnimations...] etc but if your approach works, it's probably just as fine.
You've made the view appear to be in a different place, but because you haven't actually changed its position it is still effectively in the old location for things like hit testing, etc.
I would start by animating your view's center instead of its transform. This you can do with just a UIView animation instead of a CABasicAnimation. Additionally, your view will actually end up at the correct position when the animation is complete so things should work as you expect.

Getting started creating custom view transitions

I'm looking for tutorials on creating custom view transitions.
In particular, transitions that involve elements other than just the UIViews being affected, such as playing an animation over the transition as it is happening or modifying a screenshot of the UIView being transitioned out.
I don't mean implementing the basic set of transitions (slide, fade, etc) for which there's plenty of examples on Apple's site. I'm talking about adding video/sound/additional animation while wrapping it all in a reusable transition.
I'm vaguely familiar with some of the underlying toolkits (core-animation and quartz) but I'm looking for a no-prior-experience tutorial on the subject.
I have just put together a transition class to implement your own animation in OpenGL ES.
Feel free to read about it here
CoreAnimation animations work by recording differences in a very specific subset of UIView properties. They do not respond to any user-defined properties, and simply don't do more advanced transitions than you've already seen in the demos. You could take a screenshot of your current view, save it in memory as a texture, hide the old view and simultaneously show an OpenGL view. Then using the screenshot texture and various mesh animations, you could render your custom transition (including alpha blending around the crumpled/folded edges), then dispose of the OpenGL view to fully reveal the target view. Seems like a fun project, and you'd be in rare company to accomplish it.
Here is a quick guide to using the standard UIView transitions.
http://chris-software.com/index.php/dev-center/view-transitions/
If you want to fade into a view use something like this. This works with any type of element with an alpha property, such as UIImageViews, etc.
someView.alpha = 0;
[viewController.view addSubview:someView];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:.5];
[UIView setAnimationDelegate:self];
someView.alpha = 1;
[UIView commitAnimations];