Setting a property twice while animating - iphone

What happens if I set a property twice to two different values inside of an animation block? If I execute the following pseudocode:
myView.frame = CGRectMake(0, 0, 50, 50); // state 0
[UIView beginAnimations:#"showBanner" context:NULL];
{
[UIView setAnimationDuration:2];
myView.frame = CGRectMake(0, 20, 50, 50); // state 1
myView.frame = CGRectMake(0, 10, 50, 50); // state 2
}
[UIView commitAnimations];
which of the following results should I get?
The frame animates from state 0 through state 1 to state 2.
The frame animates from state 0 directly to state 2, ignoring state 1.
I would expect result #2 to happen because I would think that the state of the properties is recorded when the animation is committed. I'm getting a behavior in my app which seems to indicate that result #1 is happening, hence my question.

Actually the answer is 3. None of the above.
The animation block will only animate the last state change for the property. So in your case the frame will animate from state 1 to state 2.

(2) The frame animates from state 0 directly to state 2, ignoring state 1.

I needed an answer to this question and didn't find either one given here satisfactory. I built a quick test that placed a small subview like this:
- (void)viewDidLoad {
[super viewDidLoad];
self.testView = [[UIView alloc] initWithFrame:CGRectMake(0,0,40,40)];
self.testView.backgroundColor = [UIColor redColor];
[self.view addSubview:self.testView];
}
And then provided two alternative animations like this:
- (void)animateWithSimpleBlock {
[UIView animateWithDuration:2 animations:^{
self.testView.frame = CGRectMake(200,200,40,40);
self.testView.frame = CGRectMake( 0,300,40,40);
}];
}
- (void)animateWithQualifiedBlock {
[UIView animateWithDuration:2 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
self.testView.frame = CGRectMake(200,200,40,40);
self.testView.frame = CGRectMake( 0,300,40,40);
}];
}
Here's what happens: on animateWithSimpleBlock, the testView jumps in a single frame (no animation) from it's initial 0,0 position to the intermediate position 200,200. From there, it animates over 2sec to the final 0,300 position.
But animateWithQualifiedBlock animates the testView smoothly from it's initial 0,0 position to the final 0,300 position. This is the behavior I need (b/c I'm building up new view positions with looping methods called in the animation block).

Related

IOS uiview brightness change

I have two UIViews on my screen. I need to do the following:
If I increase the first view's alpha value, the second UIView alpha value should decrease. The reverse is also true.
Please show me an example of how to do this.
Perhaps something like this can help you to start:
// Displays second view and hide first view.
[UIView animateWithDuration:0.5
delay:0.0
options: 0
animations:^{
myFirstView.alpha = 0.0f;
mySecondView.alpha = 1.0f;
}
completion:^(BOOL finished){
NSLog(#"Done!");
}
];
The reverse case can be produced by reversing the alpha values.

How to impelment Phone call animation like iPhone's default Phone application does?

My application has VOIP calling. In that I want to implement animation like iPhone's default Phone application does when User Clicks on Call button on dial Pad and animation that is done on End call button.
I have researched alot about this but haven't find anything yet. Any help will be appreciated on this topic.
Right now I have implemented scaling animation like below:
- (void)animateFadingOut{
self.view.transform = CGAffineTransformMakeScale(1.00, 1.00);
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDelegate:self];
[self performSelector:#selector(push) withObject:nil afterDelay:0.35];
self.view.transform = CGAffineTransformMakeScale(0.00, 0.00);
//set transformation
[UIView commitAnimations];
}
- (void)push
{
self.view.transform = CGAffineTransformMakeScale(1.00, 1.00);
// push navigation controloller
CallViewController *objCallViewController = [[CallViewController alloc] initWithNibName:#"CallViewController_iPhone" bundle:nil];
[self setHidesBottomBarWhenPushed:YES];
[self.navigationController pushViewController:objCallViewController animated:NO];
[objCallViewController release];
[self setHidesBottomBarWhenPushed:NO];
[[AppDelegate shared] setTabHidden:TRUE];
}
But It is not giving me exact animation that default Phone application has
Here is what I might try if I was trying to create animations.
CGRect movementFrame = self.view.frame;
//Make position and size changes as needed to frame
movementFrame.origin.x = 0;
[UIView animateWithDuration:0.5
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
/*
Animation you want to commit go here
Apply movementFrame info to the frame
of the item we want to animate
*/
//If you wanted a fade
self.view.alpha = !self.view.alpha //Simply says I want the reverse.
self.view.frame = movementFrame;
//Example of what you could do.
self.view.transform =CGAffineTransformMakeScale(1.00, 1.00);
} completion:^(BOOL finished) {
//Things that could happen once the animation is finished
[self push];
}];
This has not been tested for your case. Therefore I am also not sure if it will help you, but hopefully it will. Good luck to you.
*Edit*
So I reviewed the animation on an iPhone and it appears to me to be a series of animations happening at once.
You have what I presume to be the UIActionSheet animating down.
The top section overlay sliding up its y-axis.
Then you have, which I haven't mastered yet, a split in the back view that animates its x-axis in opposite directions which cause the split.
Finally you have the new view scale up to take frame for the effect.
I can't say 100% this how they have done it, however if I was going to attempt to recreate this, I would likely start here.
Hello there so after just quickly coming up with an animation I got pretty close it could use some tweaks.
It took me three views to do a
topView, bottomView, and backView.
Also took into account the view that you would be loading in. viewToLoadIn
`-(void)animation{
CGRect topMovementFrame = self.topView.frame; //Set dummy frame to modify
CGRect bottomViewFrame = self.bottomview.frame;
topMovementFrame.origin.y = 0 - self.topView.frame.size.height; //modify frame's yAxis so that the frame sits above the screen.
bottomViewFrame.origin.y = self.view.frame.size.height; //modify frame's yAxis to the it will sit at the bottom of the screen.
[self.viewToLoadIn setFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
[UIView animateWithDuration:0.5
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
//Animation
self.topView.frame = topMovementFrame; //Commit animations
self.bottomview.frame = bottomViewFrame;
self.backView.alpha = !self.backView.alpha;
self.backView.transform = CGAffineTransformMakeScale(100, 100);
self.viewToLoadIn.transform = CGAffineTransformMakeScale(2.0, 3.0);
*MAGIC*
} completion:^(BOOL finished) {
//Completion
//Clean up your views that you are done with here.
}];
}`
So then When they pressed the button I had setup this animation would happen.
Also at first I thought that the setup might contain a UIActionStyleSheet. which it still might but this is a pretty handy built in functionality. But the fact that you can interact with the screen lead me to think a custom view. It would be easier in my opinion.
I hope this helps you even if it just a little bit.
Take care ^^

How to decrease the width of a frame of an UIImage gradually without distorting it?

I think this is a very basic question, but I am struggling with this one.
I have a screenshot (an UIImage) which I put into an UIView (called screenShotView in my sample below). I want to get rid of this screenShotView by gradually revealing what is behind this screenShotView. Right now my screenShotView SQUEEZES to the left, but I would like its FRAME to become less and less until the screenShotView is no longer seen (without Squeezing).
This is my code. If I did the same transformation with an UITextView (instead of an UIImage) it would work exactly how I would like it to behave (without transformation).
Perhaps I don't get the concept of framing UIImages?
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:10];
[screenShotView setFrame:CGRectMake(0, 0, 0, 480)];
[UIView commitAnimations];
And this is how it looks like in the middle of the animation:
And this is how I would like it to look like in the middle of the animation:
This is the code updated to Codo's suggestions (see below), with the result that I have no animation anymore. The blue screen simply pops up once the button is pressed. I guess that I am doing something wrong with adding the subviews -- the problem appears to be that no subviews are added and can therefore not disappear:
-(IBAction)showNextText
{
screenShotView = [[UIImageView alloc] initWithImage:[self screenshot]];
[screenShotView setFrame:CGRectMake(0, 0, 320, 480)];
[screenShotScrollView setFrame:CGRectMake(0, 0, 320, 480)];
[self.view addSubview:screenShotScrollView];
[screenShotScrollView addSubview:screenShotView];
screenShotScrollView.scrollEnabled = NO;
[self setUpNextText];
[self removeOldText];
}
-(void)setUpNextText
{
NSString* secondText = #"This is the second text shown if the user clicks next.";
textView.text = secondText;
textView.textColor = [UIColor redColor];
textView.backgroundColor = [UIColor blueColor];
}
-(IBAction)removeOldText{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:5];
[screenShotScrollView setFrame:CGRectMake(0,0,320,480)];
[UIView commitAnimations];
}
Answer to question
It's actually very simple: I've made a sample app to get the star wars(just calling it here) transition working. For simplicity I'll just call the two views firstView and secondView. firstView is shown (would be your screenshot) and secondView will slide in from the left. I've put a button on each view to animate the transition, which is wirde to doTransition. The important part is to set the sliding in view's properties clipsToBounds = YES and autoresizesSubviews = NO. That's it. I'll post some screenshots.
- (void)viewDidLoad
{
[super viewDidLoad];
secondView.frame = CGRectMake(0, 0, 0, 480);
secondView.clipsToBounds = YES;
secondView.autoresizesSubviews = NO;
[self.view addSubview:firstView];
[self.view addSubview:secondView];
}
- (IBAction)doTransition
{
[UIView animateWithDuration:1.0
animations:^{
self.secondView.frame = CGRectMake(0,
0,
320,
480);
}];
}
Research on page curl
I did some research on the page turn / curl effect. Mainly this is all present in iOS, with little effort you can create the iBook page turn effect, but it's accessing private methods and classes. I still encourage anyone to have a look at it, cause it might some day be opened.
Apple's iBooks Dynamic Page Curl - Demo App by Steven Troughton-Smith
Leaves - An App with a custom page curl by Tom Brow, tried, compiled and looks nice!
App Store-safe Page Curl animations - Article on Tom Brow's Leaves App which has been branched (twoPages) by the author Ole Begemann
Implementing iBooks page curling using a conical deformation algorithm - With a MacOS Demo App, very professional and advanced, though not an option for a quick shot still inspiring. Download the App!
The anatomy of a page curl - Mathematical approach
I guess you have to put your upper view into a UIScrollView. Then you set the content size to be the same as the size of the UIScrollView and disable scrolling.
Next you do your original animation (setFrame) on the UIScrollView.
Basically, you then use the UIScrollView to introduce a separate coordinate system for the inner view. When the outer view (the scroll view) is made smaller, it will not distort the inner view, but clip it.
CGRect fillRect = self.view.bounds;
leftImageView.clipsToBounds = YES;
leftImageView.contentMode = UIViewContentModeTopLeft;
leftImageView.frame = fillRect;
rightImageView.clipsToBounds = YES;
rightImageView.contentMode = UIViewContentModeTopRight;
rightImageView.frame = CGRectMake(fillRect.size.width, 0, 0, fillRect.size.height);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:3];
leftImageView.frame = CGRectMake(0, 0, 0, fillRect.size.height);
rightImageView.frame = fillRect;
[UIView commitAnimations];
Don't animate the frame but the center. See the documentation here.
Also, if you only need iOS 4 compatibility, use -animateWithDuration:animations:
[UIView animateWithDuration:10
animations:^{ screenShotView.center = CGPointMake(x, y) } ];
I'm not sure I fully understand how you want your view to disappear.
If it's supposed to become more and more transparent, use the following code (instead of setFrame):
[screenShotView setAlpha: 0.0f];
If it's supposed to become smaller and smaller (but keep its center), then try:
[screenShotView setFrame:CGRectMake(screenShotView.frame.x, screenShotView.frame,y, 0, 0)];

iPhone effect comment box

I've just used Instagram application. I like the effect when I click on comment.
When you click "comment" you'll see a fade in view for insert the comment text.
How can I implement something like this?
Here two screenshot's:
Set a UIAnimation. Start the animation with the alpha of the view at 0, and then end the animation with the alpha of that view to 1, and commit the animation. And voila, you have a view that fades in.
It's easy. Create your view. When the user clicks the button, set the alpha of that view to 0 and set the size to smaller than your final size, etc.
lets say your view is called myView. you'd write:
myView.alpha = 0;
myView.frame = CGRectMake(50, 50, 100, 100);
[self.view addSubVew: myView];
[UIView beginAnimations:#"View Fade" context:nil];
[UIView setAnimationDuration: .25];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
and then you set the alpha to 1 and increase the size of the view
myView.alpha = 1
myView.frame = CGRectMake(25, 25, 200, 200);
and then you commit the animations
[UIView commitAnimations];
It's something like that, i wrote it off the top of my head so I apologize for any syntax errors or anything. But that's pretty much how it's done.

CAAffineTransformationMakeRotation problem

I have a problem with CAAffineTransformationMakeRotation. M trying to rotate a UIView with 22.5 degrees in ViewDidLoad, and after a delay of 1 sec,the View flyin to the screen.
the code is:
-(void)ViewDidiLoad{
imgView1 = [[UIView alloc] initWithFrame:CGRectMake(20,150,.1,400)];
[imgView1 setBackgroundColor:[UIColor blackColor]];
[self.view addSubview:imgView1];
CGAffineTransform trans = CGAffineTransformMakeRotation(3.14159/8);
imgView1.transform = trans;
[self performSelector:#selector(img1_enter) withObject:nil afterDelay:1];
}
-(void)img1_enter{
CGRect frame = [imgView1 frame];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:2.99];
frame.origin.x = 550;
[UIView commitAnimations];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:2.99];
[imgView1 setFrame :frame];
[UIView commitAnimations];
}
The problem is that when this view fly's in..its width and height changes. I've tried without rotating the View(i.e without AffineTransformation), it works properly.
Is there any other method to rotate the View??
You could incorporate the already existing transform to preserve the current size respectively aspect ratio:
imgView1.transform = CGAffineTransformConcat(trans, imgView1.transform);
Also the documentation of the UIView class says that the frame property is undefined if the transform is not the identity transform, so you must not use it after you applied a rotation.
The frame-rectangle represents the position and size of the view within the coordinate-system of its superview. The bounds-rectangle represents the inner coordinate-system of the view, so the bounds-rectangle is sort of responsible for the actual pixel-amount (respectively the amount of columns and rows) of the view.
If the contentMode is set to UIViewContentModeRedraw and you alter the frame-rectangle, then the size of the bounds-rectangle automatically gets adjusted that it fits the size of the frame-rectangle and vice-versa, else the bounds-rectangle stays untouched. For rendering the difference between the frame-rectangle and the bounds-rectangle is compensated by an automatically created transform-matrix.
The last two sentences are only true, iff the transform-property of the view is the identity matrix. If it isn't, the frame-property is invalid and you alone are responsible to provide a proper transform from the coordinate-system of the view to the coordinate-system of its super-view. So if you want to apply a rotation, you also have apply a proper translation and scaling to get the view where you want it to be relative to the coordinates of its super-view.
So in your case, you could set the bounds-rectangle to CGRectMake(-width/2, -height/2, width, height) and set its transform to
CGAffineTransformConcat(
CGAffineTransformMakeRotation(angle),
CGAffineTransformMakeTranslation(x, y)
)
, where x and y are the center-coordinates of the view within the coordinate-system of its super-view.