How to stop an UIView animation - objective-c

I have several UIImageViews within a UIScrollView that I want to wiggle when the user long-presses one of them. So similar to the behavior you get when you long-press an icon in your iPad/iPhone menu.
So I have the following:
- (void)startWiggling {
for (UIImageView *touchView in [scrollView subviews]) {
[UIView beginAnimations:#"wiggle" context:nil];
[UIView setAnimationDuration:0.1];
[UIView setAnimationRepeatAutoreverses:YES];
[UIView setAnimationRepeatCount:FLT_MAX];
//wiggle 1 degree both sides
touchView.transform = CGAffineTransformMakeRotation();
touchView.transform = CGAffineTransformMakeRotation(-0.0174532925);
[UIView commitAnimations];
}
}
- (void)stopWiggling {
NSLog(#"Stop wiggling");
}
This works fine. The issue is... How can I make it stop wiggling after the user has pressed a button? I have a button and connected it etc and it's reaching the stopWiggling method, so that's fine. But so...
How do I remove the UIView animation from these UIImageViews?
Can I bind this action to the user pressing the home button on their device?

#import <QuartzCore/QuartzCore.h>
then
[myView.layer removeAllAnimations];
or
[self.view.layer removeAllAnimations];

Related

How to replace button with an animation in Xcode

I have a UIButton in my code that moves steadily across the screen. Currently, when the user presses the button, the alpha changes to 0 and it just disappears. What I'd like to do is run a separate animation after the button is pressed/it has disappeared. Seems easy enough but the catch is I need to run the animation at the exact point of the button when it is pressed. And I'm drawing a blank on how to make this happen. Any help will be much appreciated! I'll post some relevant code below.
-(void)movingbuttons{
movingButton2.center = CGPointMake(x, y);
displayLink = [CADisplayLink displayLinkWithTarget:self selector:#selector(moveObject)];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
}
-(void)moveObject{
movingButton2.center = CGPointMake(movingButton2.center.x , movingButton2.center.y +1);
}
-(IBAction)button2:(id)sender {
[UIView beginAnimations:nil context:NULL];
[movingButton2 setAlpha:0];
[UIView commitAnimations];
}
Replace your button2 action with below code and implement the someOtherMethodWithAnimation method with the animation you want :)
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1];
movingButton2.alpha = 0;
[UIView commitAnimations];
[self performSelector:#selector(someOtherMethodWithAnimation) withObject:nil afterDelay:1.0];
Replace your animation with:
[UIView animateWithDuration:0.25
animations:^{
self.movingbutton2.alpha = 0.0;
// modify other animatable view properties here, ex:
self.someOtherView.alpha = 1.0;
}
completion:nil];
Just a nit picking point, but is the button in your view controller's .xib file correctly hooked up to your IBOutlets and IBActions?
UPDATE:
You are not limited to modifying that one button in your method. You add what ever code you want in the animation block (see the udated axample above).
UIView animatable properties, there is an animation section there.
Another approach could be (I am just using alpha as an example):
[UIView animateWithDuration:1.0
animations:^{
self.movingButton2.alpha = 0.0;
}
completion:^{
[UIView animatateWithDuration:0.25
animations:^{
self.someOtherView.alpha = 1.0;
}
completion:nil];
}];
This will more likely guarantee the animations will hapen one after another.

Fading UIView allows subviews to be seen

I have a UIScrollView which contains various subviews (UIImageViews, UILabels and standard UIViews). Some of the UIImageViews are partially covered by other UIViews.
However, when I fade out the UIScrollView, the partially covered parts of the UIImageViews are being exposed for the brief moment of the animation.
I want to be able to fade the scrollview and all it's contents at the same time in the same animation - i.e. not revealing any of the partially covered images.
If it's not possible, I can always add a UIView on top of all the other controls and fade it from alpha 0 upto 1 to hide everything, but I'm sure there's a way to perform a complete fade on a view and all it's subviews.
I tried this:
[UIView beginAnimations:nil context:NULL];
[scrollViewResults setAlpha:0.0f];
[UIView commitAnimations];
And I've tried this:
- (IBAction)questionGroupChanged:(UIButton*)sender {
[UIView beginAnimations:nil context:NULL];
[self fadeViewHierarchy:scrollViewResults toAlpha:0.0f];
[UIView commitAnimations];
}
- (void)fadeViewHierarchy:(UIView*)parentView toAlpha:(float)alpha {
[parentView setAlpha:alpha];
for (UIView *subView in parentView.subviews) {
[self fadeViewHierarchy:subView toAlpha:alpha];
}
}
But I've still not cracked it. Any ideas?
This happens because of the way the compositor works. You need to enable rasterization on the view's layer when fading it in/out:
view.layer.shouldRasterize = YES;
You should probably only enable this for the duration of the animation because it will take up some extra memory and graphics processing time.
Mike's answer is the correct one and he deserves all credit for this. Just to illustrate, it might look like:
- (void)fadeView:(UIView*)view toAlpha:(CGFloat)alpha
{
view.layer.shouldRasterize = YES;
[UIView animateWithDuration:0.75
animations:^{
view.alpha = alpha;
}
completion:^(BOOL finished){
view.layer.shouldRasterize = NO;
}];
}
Thus, using your scrollViewResults, it would be invoked as:
[self fadeView:scrollViewResults toAlpha:0.0f];
Did you try with UIView class methods +animateWithDuration:* (available on iOS 4 and +)
Like :
- (void)fadeAllViews
{
[UIView animateWithDuration:2
animations:^{
for (UIView *view in allViewsToFade)
view.alpha = 0.0;
}
completion:^(BOOL finished){}
];
}

Remove from superview AND enable user interaction

I'm doing some custom animations to change views in a single method. I already removed "fromView" from superView using [UIView setAnimationDidStopSelector:#selector(removeFromSuperview)], but I also want to enable user interaction after the end of the animation.
Here's my code:
-(void) switchFrom:(UIViewController*) fromViewController To:(UIViewController*) toViewController usingAnimation:(int) animation{
UIView *fromView = fromViewController.view;
UIView *toView = toViewController.view;
/*************** SET ALL DEFAULT TRANSITION SETTINGS ***************/
// Get the current view frame, width and height
CGRect pageFrame = fromView.frame;
CGFloat pageWidth = pageFrame.size.width;
// Create the animation
[UIView beginAnimations:nil context:nil];
// Create the delegate, so the "fromView" is removed after the transition
[UIView setAnimationDelegate: fromView];
[UIView setAnimationDidStopSelector:#selector(removeFromSuperview)];
// Set the transition duration
[UIView setAnimationDuration: 0.4];
/*************** IT DOESN'T WORK AT ALL ***************/
[toView setUserInteractionEnabled:NO];
[UIView setAnimationDelegate: toView];
[UIView setAnimationDidStopSelector:#selector(setUserInteractionEnabled:)];
[toView setUserInteractionEnabled:YES];
// Add the "toView" as subview of "fromView" superview
[fromView.superview addSubview:toView];
switch (animation) {
case AnimationPushFromRigh:{
// Position the "toView" to the right corner of the page
toView.frame = CGRectOffset(pageFrame, pageWidth,0);
// Animate the "fromView" to the left corner of the page
fromView.frame = CGRectOffset(pageFrame, -pageWidth,0);
// Animate the "toView" to the center of the page
toView.frame = pageFrame;
// Animate the "fromView" alpha
fromView.alpha = 0;
// Set and animate the "toView" alpha
toView.alpha = 0;
toView.alpha = 1;
// Commit the animation
[UIView commitAnimations];
}
.
.
.
Any idea how can I call this two methods in setAnimationDidStopSelector and actually make them work together?
EDIT 1
Tried #safecase code like this, replacing this commented block:
/*************** IT DOESN'T WORK AT ALL ***************
[toView setUserInteractionEnabled:NO];
[UIView setAnimationDelegate: toView];
[UIView setAnimationDidStopSelector:#selector(setUserInteractionEnabled:)];
[toView setUserInteractionEnabled:YES];
*************** IT DOESN'T WORK AT ALL ***************/
// Remove the interaction
[toView setUserInteractionEnabled:NO];
[fromView setUserInteractionEnabled:NO];
// Create the animation
[UIView animateWithDuration:0.4 animations:^{
[fromView performSelector:#selector(removeFromSuperview)];
}
completion:^(BOOL finished){
[UIView animateWithDuration:0.4
animations:^{
C6Log(#"finished");
[toView performSelector: #selector(setUserInteractionEnabled:)];
}];
}];
The "toView" is removed instead of the "fromView" is removed :(
The buttons continue to be interactive during the animation
Do you know beginIgnoringInteractionEvents and endIgnoringInteractionEvents?
Normally, if you don't want any userInteraction during an animation, you would use those.
Anyway you still need correct callbacks to trigger them.
You need to define your own method, e.g. remove: and pass that as the selector. In the method, just use the passed UIView to remove it.
-(void)remove:(id)sender {
UIView *v = (UIView*)sender;
[v removeFromSuperview];
}
You can use this:
[UIView animateWithDuration:0.4
animations:^{ [self performSelector:#selector(removeFromSuperview)]; // other code here}
completion:^(BOOL finished){ [UIView animateWithDuration:0.4
animations:^{ [self performSelector:#selector(setUserInteractionEnabled:)]; //other code here}]; }];
Hope helpful.
I think u can use to enable user interaction
self.view.userInteractionEnabled=NO;
I ended up creating a Category extension to UIView… and it finally works!
UIView+Animated.h code
#import <UIKit/UIKit.h>
#interface UIView (Animated)
- (void) finishedAnimation;
#end
UIView+Animated.m code
#import "UIView+Animated.h"
#implementation UIView (Animated)
- (void) finishedAnimation{
C6Log(#"FinishedAnimation!");
[self removeFromSuperview];
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
}
#end
Then, I #imported this extension in my coordinating controller:
C6CoordinatingController.h partial code
#import "UIView+Animated.h"
And called the selector in setAnimationDidStopSelector:
C6CoordinatingController.m partial code
// Create the delegate, so the "fromView" is removed after the transition
[UIView setAnimationDelegate: fromView];
// Ignore interaction events during the animation
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
// Set the transition duration
[UIView setAnimationDuration: 0.4];
// Call UIView+Animated "finishedAnimation" method when animation stops
[UIView setAnimationDidStopSelector:#selector(finishedAnimation)];
So, I ended up using #jaydee3 and #Mundi concepts and it works like a charm!
Thank you guys!

UIPickerView : Keyboard not hiding

I have 3 UITexfield, the user can fill in the first two, but the last one is a category field and displays a UIPickerView when it's clicked.
What I've managed to do so far is :
The user clicks on the catergory textfield -> the picker view appears
Then the user clicks on another textfield -> the picker view disappears and the keyboard shows up
But know I would like to hide the keyboard when the user clicks agains on the category textfield and show the picker view.
This is what I have so far :
- (void)textFieldDidBeginEditing:(UITextField *)textField {
if(textField == categoryTextField){
[categoryTextField resignFirstResponder];
[UIView beginAnimations:#"picker" context:nil];
[UIView setAnimationDuration:0.3];
pickerView.transform = CGAffineTransformMakeTranslation(0,-236);
[UIView commitAnimations];
}else{
[UIView beginAnimations:#"picker" context:nil];
[UIView setAnimationDuration:0.3];
pickerView.transform = CGAffineTransformMakeTranslation(0,236);
[UIView commitAnimations];
}
}
But it doesn't work. Any thought why ?
You're making it too difficult. Set the picker view as the input view of the textfield, and the OS will take care of the animations for you. As each field becomes first responder, the appropriate input view (default keyboard for the text ones, your picker for the third one) will be displayed. You don't need to do any animations yourself.
I don't really see where your problem comes from. I think that maybe your translation makes the pickerView move too far. You should try that :
- (void)textFieldDidBeginEditing:(UITextField *)textField {
if(textField == categoryTextField){
[categoryTextField resignFirstResponder];
[UIView beginAnimations:#"picker" context:nil];
[UIView setAnimationDuration:0.3];
CGRect frame = pickerView.frame;
frame.origin.y = 480 - 236; // assuming your on an iPhone and your picker appears from bottom
pickerView.frame = frame;
[UIView commitAnimations];
}else{
[UIView beginAnimations:#"picker" context:nil];
[UIView setAnimationDuration:0.3];
CGRect frame = pickerView.frame;
frame.origin.y = 480; // assuming your on an iPhone and your picker disappears to bottom
pickerView.frame = frame;
[UIView commitAnimations];
}
}
Hope that helps

problem in animating view in iphone sdk?

I'm animating a view by showing and hiding view. I'm calling this method in didSelectRow.
When I click on the cell I want to hide the view and then I want to show the view. But my problem is the animation is happening from hide to show but when not from show to hide. The show to hide is happening suddenly there is no smooth animation. I'm this code.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//[tableView deselectRowAtIndexPath:indexPath animated:YES];
Song *songObj = [songsList objectAtIndex:indexPath.row];
[self hideMsg];
//int delay = 20;
//[self performSelector:#selector(hideMsg) withObject:nil afterDelay:delay];
[self showTitleWithOptions:songObj];
}
- (void)hideMsg;
{
CGRect frame = animatedSubView.frame;//CGRectMake(0,415,360,55)
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:75];
frame.origin.y = 480;// here I'm changing y to 480
animatedSubView.frame = frame;
[UIView commitAnimations];
frame = animatedSubView.frame;// now frame is CGRectMake(0,480,360,55)
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:.75];
frame.origin.y = 415;//now I'm changing y to 415
animatedSubView.frame = frame;
[UIView commitAnimations];
theTableView.frame =CGRectMake(0,230,320,190);
}
may be you can hide the view or give alpha 0.0 while its animating, and in the present view make a button action, when you click it make the present view hidden or give alpha 1.0 along with the uianimation.
It seems you are missing a . before the value 75 in the first animation code block "[UIView setAnimationDuration:75];" see your code again.
Update
You can not run two animations same time you need to wait for the first one to finish that is your main issue. Try running second animation after .75 duration by using
[self performSelector: withObject: afterDelay:];
method.