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
Related
I'm doing an animation between two UIWebView's on the TV Out screen, and i get this effect both in the simulator and with a real device:
Basically, in my 2nd UIScreen, i've got a UIWindow, and inside that there is a UIView with a black background, and inside the uiview's i'm animating between two UIWebView's using the following code:
[UIView transitionFromView:oldWebView toView:newWebView
duration:1 options:UIViewAnimationOptionTransitionFlipFromRight
completion:^(BOOL finished) {}];
And i don't understand why, mid-animation, i get the hall-of-mirrors effect instead of seeing the black background of my UIView superview. Can someone please help?
In the end, i determined this was a ios <=4.3 bug, and simply disabled animations if we're using an os older than ios 5.
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.
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.
I am rotating a UIImageView in place periodically. My view is very basic, a view inside of a UITabBar view set. If I happen to rotate my iPad while my rotation is animating then my image becomes skewed. I have checked everything I can think of in my xib file for my image, the autoresizing is turned completely off and I am not auto-resizing subviews on the parent view.
Here is my animation code:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDelay:0.0];
transform = CGAffineTransformMakeRotation(convertToRadian(myDegrees));
myImage.transform = transform;
[UIView commitAnimations];
If I take my animation out then everything works as I would expect. This rotation code appears to work fine if I do not rotate my device.
What can I do to keep the built-in rotation animation from altering my animation and skewing my images?
After many different attempts, what I ended up doing here is adding a clear view with my rotating images inside of it and setting the "auto-resize sub views" to off in interface builder. You can also do this in code as needed. I had to add the UIView placeholder because the super view containing my rotating images needed to auto-resize other view objects on rotation, but this fixed the funky skewing of my images due to animation of orientation change at the same time as animating a manual rotation in place.
Hope this helps someone.
The coordinate system gets changed. I've figured this much out too... thought I had a bug. If you save the CG ... GState, then you can revert back to the coordinate system initially used. This is in Deitel and Deitel's book. I just found it. Wanted to post it for anyone also looking.
You got a clever trick though! I might use it if this won't work.
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];