I have to give a delete thumbnail animation in my ipad application just like iphone/ipad applications delete effect.
Any body help me please sample photo is attached
If you need more details then kindly mention it in comments
I have done this using CGAffineTransformMakeRotation. Don't know there is some other better method. But What I have done is my logic you can copy that as it is and you just need to add a delete button on the left top of that view. In the following code I am just animating the thumbnail or any view just like iPad does on its home screen. One thing, You need to declare int direction globally. and every time when you will call this method you will set direction = 1;
-(void)shakeToDelete:(UIView *)shakeMe
{
[UIView animateWithDuration:0.1 animations:^
{
shakeMe.transform = CGAffineTransformMakeRotation(0.05 * direction);
}
completion:^(BOOL finished)
{
direction = direction * -1;
[self shakeToDelete:shakeMe];
}];
}
/// edit
I tried this way and got it working in my sample screen as attached in photo
You better should use an autoreverse and looped animation, cause creating animations over and over will fulfill the phone memory.
With this code, only one animation is retained.
view.transform = CGAffineTransformMakeRotation(-kDeleteAnimationAmplitude);
[UIView animateWithDuration:0.1 delay:0 options:UIViewAnimationOptionRepeat|UIViewAnimationOptionAutoreverse animations:^{
view.transform = CGAffineTransformMakeRotation(kDeleteAnimationAmplitude);
} completion:nil];
Then if you want to stop your animation, just call:
[view.layer removeAllAnimations];
Related
I am building a page browser that animates pages as 'sheets of paper' being pulled on top of off a stack of papers. In order to keep smooth animations I use 3 UIViews which are stacked on top of each other. These three views hold the current page (on top), the previous page (in the middle) and the next page (at the bottom).
In the code below, I want to drag the top view off to the right, revealing the previous page underneath. This works fine. However, after that I need to move the top page to the bottom of the stack, in order to prepare the stack of three views for the next time the user does a page flip. I use the sendSubviewToBack method for this.
My problem is that ViewSample[Top] is sent to the bottom of the stack as soon as the animation starts. How can I enforce the animation to finish (so that ViewSample[Top] has moved out of the screen completely) before it is sent to the bottom of the stack?
ViewSample[Top].center = CGPointMake(x,y);
[UIView animateWithDuration:0.5
animations:^
{
ViewSample[Top].center = CGPointMake(x+w,y); //slide away to the right
}
completion:^(BOOL finished)
{
}
];
[self.MainView sendSubviewToBack:ViewSample[Top]];
EDIT
i just ran into a very peculiar behaviour which has to do with my problem.
I followed your advice, and found that the behaviour in the 'finished' section of the animation depends on the value of the variable 'top' when it is set AFTERWARDS:
ViewSample[Top].center = CGPointMake(x,y);
[UIView animateWithDuration:0.5
animations:^
{
ViewSample[Top].center = CGPointMake(x+w,y); //slide away to the right
}
completion:^(BOOL finished)
{ [self.MainView sendSubviewToBack:ViewSample[Top]];
}
];
Top++; // THIS COMMAND AFFECTS THE LINE ABOVE!!!
In other words, when I add the line 'Top++;' another View is moved back on the stack, even though the statement sendSubviewToBack came first. This is very confusing to me. Does this make sense? Is it a bug?
The other answers correctly identified the issue. What you're running into with your updated code is a problem of execution order:
Because completion is executed only after the animation completes, your code actually executes in this order:
ViewSample[Top].center = CGPointMake(x,y);
ViewSample[Top].center = CGPointMake(x+w,y);
Top++;
[self.MainView sendSubviewToBack:ViewSample[Top]];
There are two possible solutions. You can either store the view in a variable so you have the same view in all your calls, or you can delay setting the value of Top until completion.
Option 1
UIView *viewMovingFromTopToBottom = ViewSample[Top];
viewMovingFromTopToBottom.center = CGPointMake(x,y);
[UIView animateWithDuration:0.5 animations:^{
viewMovingFromTopToBottom.center = CGPointMake(x+w,y); //slide away to the right
} completion:^(BOOL finished) {
[self.MainView sendSubviewToBack:viewMovingFromTopToBottom];
}];
Top++;
// Other code that depends on the new value of Top...
Option 2
ViewSample[Top].center = CGPointMake(x,y);
[UIView animateWithDuration:0.5 animations:^{
ViewSample[Top].center = CGPointMake(x+w,y); //slide away to the right
} completion:^(BOOL finished) {
[self.MainView sendSubviewToBack:ViewSample[Top]];
Top++;
// Other code that depends on the new value of Top...
}];
Which option makes the most sense to you depends on what you're doing. If you're chaining animations together, you may want to move most of your code into the completion block to delay it until the slide animation completes. If you have a lot of work that needs to be done right away without dependencies on animation, you may want to use option 1 to configure you animations and move on. Or you may want a mix.
Use the completion block:
ViewSample[Top].center = CGPointMake(x,y);
[UIView animateWithDuration:0.5
animations:^
{
ViewSample[Top].center = CGPointMake(x+w,y); //slide away to the right
}
completion:^(BOOL finished)
{
[self.MainView sendSubviewToBack:ViewSample[Top]];
}
];
Brian Nickel's first suggestion (local variable) did the trick. However, there was a caveat: you have to be careful in the order of statements. This does not work:
[self.MainView addSubview:LocalView];
LocalView = View[1];
...whereas this does:
LocalView = View[1];
[self.MainView addSubview:LocalView];
I first had the top version, which just makes the blank view appear.
So a working approach is to use three global views to do the page caching, and use two local views for the animation. The local views are stacked in the appropriate order, copy the data from the global views and then perform the animation.
Seems simple, but I can't get this to work with all the different methods I try.
All I want to do, is fade in an image from a black background when I open a new view controller.
So far I've tried this:
//I've set the image alpha to 0 on the storyboard already
- (void)viewDidLoad
{
[UIView animateWithDuration:5.0
delay:0
options: UIViewAnimationOptionCurveEaseIn
animations:^{
myImage.alpha = 1;
}
completion:^(BOOL finished){
NSLog(#"Done!");
}];
}
It runs, and the image comes up immediately (just doesn't seem to be animating!)
I know this is a simple question but I have already spent hours looking for a solution.
If anyone could help it would be much appreciated!
Thanks!
Animation should work from within -viewDidLoad but you may be doing something more in -viewDidLoad that is disrupting the animation.
or...
You could instead move your animation code to -viewDidAppear:
-(void)viewDidAppear:(BOOL)animated
{
//do the animation here
}
Trying here develop a side menu, but i'm facing a problem that i cannot figure out why is happening.
Here is a video sample to show what the problem is:
https://www.dropbox.com/s/i97iigus8gj2sl4/problem_side_menu.mov
When I press the menu button the labels appear first than the view controller, what I want is that the latest follow the transition animation.
I have a container view controller that manages all my views controllers.
Already did some research, but I really don't know which keywords use to find useful information.
I really appreciate any help you can provide.
The animation suggests that you have drawn your buttons on wrong view. Make sure your side menu is owner of your button.
What I would recommend doing is fading the UILabels/UIButtons as the transition happens. So in your code that hides the side menu container, do the animations there.
[UIView animateWithDuration:0.2
delay:0.0
options:UIViewAnimationOptionCurveLinear
animations:^
{
self.label.alpha = 0.0;
self.button.alpha = 0.0;
}
completion:^(BOOL finished)
{
if (finished)
{
self.label.alpha = 1.0;
self.button.alpha = 1.0;
}
}];
Whilst playing around with UIView animation, I came across a situation where I think some refactoring is needed:
The following views whose opacity are initially set to 0.0f.
Ex:
[UIView animateWithDuration:1.0f
animations:^
{
firstView.layer.opacity = 1.0f;
}
completion:^(BOOL finished)
{
[UIView animateWithDuration:1.0f
animations:^
{
secondView.layer.opacity = 1.0f;
firstView.layer.opacity = 0.0f;
}
completion:^(BOOL finished)
{
[UIView animateWithDuration:1.0f
animations:^
{
thirdView.layer.opacity = 1.0f;
secondView.layer.opacity = 0.0f;
}
completion:^(BOOL finished)
{
thirdView.layer.opacity = 0.0f;
}];
}];
}];
All 3 views are just subclass of UIView's, which are added as subviews of the main view.
This simply animates the opacity of the first view to 1.0f and then that of the second view, and then that of the third view.
Simple. Nothing special here.
My Question is:
What if I had more views, let say 100, that I wanted to perform the same action (same sequence of animation), this block of code would expand and expand.
So for the sake of refactoring and being adhered to good practice of writing code, I thought may be this could be done with less code via the use of a method and perhaps a loop.
Could you enlighten me on this in regards to refactoring; in addition, would dispatch_apply be useful here along with the refactoring process if a loop is needed?
If you wanted to animate 100 images, you would probably want to use 2 views and load alternating images into each one. I recently created a sample app on github that does exactly that:
Animating UIImages with cross-fade opacity changing
I have been trying to build an entry effect for a logo to come from the top of the screen to the bottom and remain there when a new view loads in my application. I have seen all of the tutorials that use NSTimer to bounce an image but once my logo hits the bottom it needs to exit. I'm going to read up on animation block codes to see if my solution resides there.
Apologies I'm a new be and am very grateful for the assistance.
Set logo frame to top and then:
[UIView beginAnimations: #"moveLogo" context: nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:1.0];
[UIView setAnimationCurve: UIViewAnimationCurveLinear];
logoToMove.frame = CGRectMake( final frame at the bottom );
[UIView commitAnimations];
logoToMove is your logo, give it an outlet and hook it in xib.
So you will set the initial frame and in the animation - the final frame. The animation will do the rest of the job.
Change UIViewAnimationCurveLinear to a desired one if you don't like that. Also the duration to speed up or slow down the movement.
To remove the view at the end of your animation, the easiest way would be to use blocks :
logoToMove.frame = topRect;
[UIView animateWithDuration:duration
animations:^{
logoToMove.frame = bottomFrame;
}
completion:^(BOOL finished) {
[logoToMove removeFromSuperview];
}
];
Doing it like that gives you control over the animation and on what to do once it's finished in a single method