I have a UIScrollView here where I'm adding displaying a label in the middle of the screen when the user has scrolled to a page, the problem is that while the animation is going the user can't scroll to the next page (all user interaction seem to be disabled) until the animation is over.
Here's my code for displaying the label.
if(!scrollView.dragging)
[UIView animateWithDuration:0.3
delay:0.3
options:UIViewAnimationOptionCurveEaseOut
animations:^(void){
[vesselNameLabel setFrame:frame];
}
completion:^(BOOL finished){}];
So how would I get out of this canceling user interaction on the scrollview?
Okay, so I figured this out.
Turns out UIView's block animation by default blocks user interaction, and to get around it you need to pass UIViewAnimationOptionAllowUserInteraction as one of the options. Hopefully someone else will have some use of this information as well.
we noted a strange behaviour if alpha becomes 0 ... touches are ignored.
Related
I'm new to programming Xcode/objectiveC and this questions seems like it should be painfully obvious but I cannot find an answer; how do i move to a different view controller after an animation completes (without a button or other user interaction). in other words go back to the "home" screen automatically after it finishes. right now the image that is animated just stops moving and stays there after the animation finishes and i'm stuck in that viewController.
i'm guessing the coding should have something to do with the selector but i'm not sure
[UIView setAnimationDidStopSelector:#selector ???];
thanks!
UIView's animateWithDuration has a completion block in which you can put code that is executed when the animation is completed.
[UIView animateWithDuration:duration
animations:^{
animations
}
completion:^(BOOL success) {
[self performSegueWithIdentifier:#"YOUR_SEGUE"];
}];
I am not much into iOS animation. What I am trying to achieve is a simple message view that slide vertical from bottom of screen to a given y, then after few instants the UIView rollback in vertical to go off screen.
[UIView animateWithDuration:0.5f
animations:^{
self.messageView.frame=CGRectMake(x, y -80, width, height);
}
completion:^(BOOL finished){
if (finished) {
[UIView animateWithDuration:0.5f delay:2.0f options:UIViewAnimationOptionCurveLinear
animations:^{
self.messageView.frame=CGRectMake(x, y + 80, width, height);
}
completion:^(BOOL finished){
// do something...
}
];
}
} ];
This is working fine, but I am having a problem using this mechanism in a iOS UITabBar application: when I change tab, the animation stop, I can infact see that "finished" completion is "false". Therefore the second block is not called, and the message view stays on.
Here are the questions:
my first concern is to understand if the code I have written is correct, regarding the nested animations.
I could solve by ignoring 'finished' and execute code anyway, but I don't feel it is a good idea
within the last completion block, I have put some programming logic, basically I am restoring few UIButtons state, and some other little UI change. At this point I don't know if it is a good idea, it seems not, but how can let the UI knows that the message view has disappeared. NSNotification and KVO seems a bad idea when fast responsive UI change are involved.
You can stop all animations for a layer by sending the layer a removeAllAnimations message.
[sel.view removeAllAnimations];
I have seen many questions in this forum which gives answer to this topic "UIButton inside a UIView, when animated doesn't work", but after having tried out the answers like
a) UIViewAnimationOptionAllowUserInteraction to the options
b) subView.setUserInteractionEnabled = YES
c) [button addTarget:self action:#selector(buttonPressed) forControlEvents:UIControlEventTouchUpInside];
none of them is working for me :-(
Here is the scenario. App is in landscape mode and a UIView called menuView is placed at x=480,y=0. Its height=200 and width=150. So, when I tap the button on the top right corner, the following code is executed
- (IBAction)showMenu {
[menuView setUserInteractionEnabled:YES];
[optionsButton setUserInteractionEnabled:YES];
[UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationCurveEaseOut | UIViewAnimationOptionAllowUserInteraction
animations:^{
self.view.frame = CGRectOffset(self.view.frame, 0, 200);
}
completion:NULL];
}
Output?: View is appearing, but optionsButton inside the menuView is not clickable. I hooked up to an event, did an NSLog(#"Options button clicked"), but nothing happens :-(
Please tell me what I am doing wrong?
Update: When I place the subview that is "menuView" inside the self.view, then upon running and click the optionsButton, I get the NSLog message. Only if I specify the origin.x of menuView to be 480 and above, it doesn't work.
If you can see the UIButton, its userInteractionEnabled (YES by default!) is set, and its superview's userInteractionEnabled in the whole hierarchy is YES - you should be able to interact with it.
An animation will never change your userInteractionEnabled property! So what you are doing there is simply unnecessary. If you try to enable interaction during animation - that's a different story and is just an option passed to the animation message.
So if that's not your problem (and is probably not), then I guess one of the superview's frame is cropping the UIButton!
Now you see, if a UIButton (or any UIView) is outside a UIView's frame, it can still be visible, unless clipsToBounds is set on the superview.
And the outcome of that situation is: You can see me, but you can't touch me.
In my case missing a constraint on the height of the containing view caused the view height to be 0. Buttons were visible, below the view, but untouchable.
For me it was all about an overlooked mistake in the animation code itself. Where my new height was being called I was actually calling my new width, and where my new width was being called I was actually calling my new height, therefor causing the UIView to be super long yet super narrow, thus pushing all content within the center of view, outside of the view reach.
Change your UIViews background color to Red so that you can actually see where it animates to.
If your UIView is within another view, turn on clipSubviews so that you only see what is actually enabled within the subView.
Run your project.
If your UIView is not its normal height and width, more than likely you have overlooked some code in your animation call.
Make sure that your x, y, width, height are being shown in the correct orders within the animation code.
In my case, it seems like my animated transitioning is not yet completed. I forgot to to put completeTransition:Bool at the end of my animateTransition:context method.
I want to click _transitButton to call onTransitButtonDidClick to move _rightView.
The problem is the button cannot do as I set self.transitButton.frame = CGRectMake(0, 0, 30, 20);.
update:
_transitButton original frame is (0,280,30,20)
the result is, the button move from the original frame to (0,0,30,20), but quickly move back to original point.
why it went back?
why and how to solve this issue?
- (IBAction)onTransitButtonDidClick:(id)sender {
[UIView animateWithDuration:0.3
delay:0.0
options:UIViewAnimationCurveEaseInOut
animations:^{
[_rightView setFrame:CGRectMake(40,0,320,548)];
[_transitButton setFrame:CGRectMake(0,0,30,20];
}
completion:nil];
}
you are using autolayout in your xib and constraints keep the button in place.
with animation it appears to work because the constraints arent evaluated for animations.
so either turn off AUTOLAYOUT for this xib or modify the appropriate constrains.
(I tried this with a small sample app and that's it.)
I am trying to make something relatively simple, make a wheel spin 90degrees when the user touches a button, for the most part what I have done so far works the first time, but thereafter the image won't move. I want it to keep its new position and rotate 90degrees thereafter from the new position, I have
[UIView setAnimationBeginsFromCurrentState:YES];
but that doesn't seem to work
I added an NSTimer to "reset" the original image orientation, so that the wheel springs back to the original position and then rotates again when the user touches it. ... however this isn't really what I want.
Is there a way to make the image keep rotating 90degrees so four touches by the user would put the image back to its original position. Thanks for any help!!
here is the sample code
-(IBAction) rotatewheel:(id)sender {
[UIView setAnimationDuration:1];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationRepeatCount:1];
wheel.transform = CGAffineTransformMakeRotation(M_PI/4);
[UIView commitAnimations];
returnwheelTimer = [NSTimer scheduledTimerWithTimeInterval:1.1 target:self selector:#selector (returnwheel) userInfo:nil repeats:NO];
}
-(void) returnwheel {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:.5];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationRepeatCount:1];
wheel.transform = CGAffineTransformMakeRotation(M_PI);
[UIView commitAnimations];
}
Instead of:
wheel.transform = CGAffineTransformMakeRotation(M_PI/4);
use
wheel.transform = CGAffineTransformRotate(wheel.transform,M_PI/4);
That way it will apply the new tranformation to the current one, instead of replacing it.
There are three easy ways to implement this.
1) Make your app in a game engine, such as Unity3D, rather than in XCode. Make an animation of the spinning wheel and script it to start on the button push. This is relatively simple to do and there are many good existing tutorials. I recommend using iGUI by Avaam Studios (I am not affiliated with them or biased in any way).
2) Create an NSObject with an array of photos and start a stop motion animation of the wheel spinning on the button push. A thread on this subject can be found here.
3) If you want the wheel to spin 90 degrees FROM its last location, so that it can be spun full circle (36) after four clicks, then a different approach is needed. I recommend making the button be replaced with a different, identical one each time it is pushed. That way you do not need to do the math on the number of pushes. You would have four different IBOutlets (one for each identical button) and each button would a) turn the image 90 degrees, then b) disappear and be replaced with another button. I have not seen any practical implementations of this but it is feasible. Here is a thread on the subject of multiple methods on one button (possibly a better alternative to my idea).