iOS - How to slow down UISlider animation? - ios

I'm trying to slow down the animation of the UISlider when changing values.
So far, I've tried the old UIView animation method:
[UIView beginAnimations:#"slider" context:nil];
[UIView setAnimationDuration:5.0];
[self.slider setValue:2 animated:YES];
[UIView commitAnimations];
And the new blocks based method:
[UIView animateWithDuration:5.0
animations:^{
[self.slider setValue:2 animated:YES];
}];
I've tried with and without the animated:YES value set. In all cases, the slider simply animates at the default speed.
Is there another tactic I should be looking at to customize the speed of the animation?
Should I subclass the slider and override anything there?

Check out the OBSlider, a UISlider subclass with variable scrubbing speed (as seen in the iPod app on iOS) by Ole Begemann. I'm not saying it is exactly what you want but you can see how it is implemented since the code is hosted at GitHub. Basically, it subclasses UISlider and overrides the touch tracking methods:
beginTrackingWithTouch:withEvent:
continueTrackingWithTouch:withEvent:
endTrackingWithTouch:withEvent:

Related

UIView animateWithDuration not animating in ios8

I have implemented a custom segue class for emulating the push transition without navigation bar. The trick is to take to snapshots, add them to the view, replace the viewController, move the snapshots, and finally remove them. This emules a horizontal movement of the viewController, but actually only two UIImagesView are moved.
The following code implements this.
self.destinationImageView.frame = offsetFrameD;
self.sourceImageView.frame = offsetFrameS;
//ViewController replacement
[self.sourceViewController presentModalViewController:self.destinationViewController animated:NO];
//Overpose the snapShot who will simulate the transition between vies.
[destinationView addSubview: self.sourceImageView];
[destinationView addSubview: self.destinationImageView];
[UIView animateWithDuration:1.0
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
self.destinationImageView.frame = self.finalFrameD;
self.sourceImageView.frame = self.finalFrameS;
}
completion:^(BOOL finished) {
[self.sourceImageView removeFromSuperview];
[self.destinationImageView removeFromSuperview];
}];
This code worked with iOS 7. However, when using iOS 8, it seems like the animation is not performed. The destinationImageView and sourceImageView are directly moved to the finalPosition (WITHOUT ANIMATING) and the completion block is not called, so both UIImageView are not finally removed.
Does anyone knows how the animation should be performed with iOS 8?
You should adjust the auto layout constraints and not the frames position. Have a look at this solution. I hope it helps.
UIView transitionWithView & setting the frame no longer works iOS8
Use the following line of code before the start of the animation:
[UIView setAnimationsEnabled:YES];

Check if UIView is currently animating

I have two animations running; show search bar and show banner. Both those animations are resizing the same view and if they are running on the same time (Which they are) the latest animation will cancel the resize. Is there anyway to check if UIView is currently animating and then standby for animation?
I'm pretty sure I'm not using CAAnimations, since Cocoa not is detecting such class.
This one is running when an ad was received. Unfortunately, that is the same time as ShowSearch is running.
- (void)adViewDidReceiveAd:(GADBannerView *)bannerView {
if (!hasloaded) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationCurve: UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration: 1.0];
[bannerView_ setFrame:CGRectMake(0, self.view.frame.size.height, bannerView_.frame.size.width, bannerView_.frame.size.height)];
// move and grow
[bannerView_ setFrame:CGRectMake(0, self.view.frame.size.height-50, bannerView_.frame.size.width, bannerView_.frame.size.height)];
// set original position
[UIT setFrame:CGRectMake(UIT.frame.origin.x, UIT.frame.origin.y, UIT.frame.size.width, UIT.frame.size.height)];
// move and grow
[UIT setFrame:CGRectMake(UIT.frame.origin.x, UIT.frame.origin.y, UIT.frame.size.width, UIT.frame.size.height-50)];
[UIView commitAnimations];
hasloaded = true;
}
}
You can use the completion block in the UIView method +animateWithDuration:animations:completion: (which is a more modern alternative to beginAnimations/commitAnimations) to chain multiple animations (I'm guessing this is what you want to do?).
If you select your code while entering it and press control + K, you will preserve formatting and make it pretty. Try it. Reading the wall of text made from pasting code into a true-type non-color-formatted environment.
Nick Weaver says:
A UIView has a layer (CALayer). You can send animationKeys to it which will give you an array of keys which identify the animations attached to the layer. I suppose that if there are any entries, the animation(s) are running. If you want to dig even deeper have a look at the CAMediaTiming protocol which CALayer adopts. It does some more information on the current animation.

Choppy UIView animation

I use a UIView animation to randomly animate 5 squares (UIButtons) around the screen. Depending on a user selection, there are anywhere from 2 to 5 squares visible. When only 2 are visible, the other three's hidden values get set to YES, so they are actually still animating (right?), they just aren't visible. But when only 2 are visible, the animation is smooth, but when all five are visible, the animation gets choppy. I'm not really sure how to describe it, because the squares are still moving at the correct speed and moving to the correct points; the choppiness isn't terrible, just bad enough to be noticeable. Is there any way to get rid of it? This is the code I use to animate the squares:
Edit: changed animations to block:
[UIView animateWithDuration:animationSpeed
delay:0
options:UIViewAnimationOptionCurveLinear
animations:^{
view.center = destPoint;
}
completion:^(BOOL finished){
if([view isEqual:squareThree])
[self moveBadGuys];
}
];
/*for(UIButton* button in squareArray) {
if(!shouldMove)
return;
[UIView beginAnimations:#"b" context:nil];
[UIView setAnimationDuration:animationSpeed];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
view.center = destPoint;
[UIView commitAnimations];
}*/
Edit: the view presenting this is the third in a stack of three UIViewController presented with
ViewController* controller = [[[ViewController alloc] init] autorelease];
[self presentModalViewController:controller animated:NO];
Does this way of presenting views eat up memory?
There are a few things that can cause this. It always comes down to how complex the content is. Also, simulator can be really bad about handling animation, so be sure you are testing on real hardware.
Are there large images on the buttons? Are the buttons casting shadows? Those things can slow it down.
Also- use block based animation. Not the old begin-commit methods.
Not exactly sure why it's slow, but have you tried nesting the thing differently?
if(!shouldMove)
return;
[UIView beginAnimations:#"b" context:nil];
[UIView setAnimationDuration:animationSpeed];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
for(UIButton* button in squareArray) {
view.center = destPoint;
}
[UIView commitAnimations];
does (almost - the logic is a bit different in the !shouldMove case, but that's a different story) the same, but in a cleaner way.

Having problems allowing interaction in UIView animation

I have the following block of code to fade out an introView(UIView)
// Hide intro view after 5 seconds
[UIView animateWithDuration: 1.0
delay: 5.0
options: (UIViewAnimationOptionAllowUserInteraction |UIViewAnimationOptionCurveLinear)
animations: ^{
introView.alpha = 0;
}
completion: ^(BOOL finished) {
[introView removeFromSuperview];
}];
I have a skip button inside the introVew but there is no interaction whatsoever, am I missing something? I have to add this is a Universal app targeting 3.2 and I'm using XCode 4.2
Pretty sure this is impossible pre-4.0:
UIView userInteractionEnabled Docs
During an animation, user interactions are temporarily disabled for
all views involved in the animation, regardless of the value in this
property. You can disable this behavior by specifying the
UIViewAnimationOptionAllowUserInteraction option when configuring the
animation.
There seems little point in targeting 3.2 in an app you haven’t released yet.
Are you setting your button alpha to 0?
If yes here is an interesting thing about animation.
What you see on the screen during the animation is not what the application sees.
The moment you set your alpha to 0, the alpha is 0 for that view, even if you are still seeing it on the screen.
Also, a view that has an alpha lower that 0.05 (don't recall the exact number) won't get touch event.
What you can do is to implement the - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event of that view's superview. or the touchesEnded... as you like.
(Assuming that your not setting it's alpha to 0.)
So you can test for touche that occur where the button is, or just remove that button and let any touch on the screen cancel your animation.
You may also be interested in this post:
Core Animation, unexpected animated position and hitTest values
I found another circumstance which could cause this. I haven't seen this answer anywhere else. It does not deal with alpha at all.
If you use a delay in the call to UIView.animate(), then even if you specify the .allowUserInteraction option, the view does NOT receive touches during the delay period. I have no idea why, but I could help it by moving the code block to another function, and using a performSelector after the same delay seconds, and in the block I run the code without delay.
I had the same problem with a button that I animated with changing the alpha. Cueing off VinceBurn's answer...
What you see on the screen during the animation is not what the application sees. The moment >you set your alpha to 0, the alpha is 0 for that view, even if you are still seeing it on the >screen.
AND view that have an alpha lower that 0.05 (don't recall the exact number) won't get touch >event.
… the simple solution of just making the minimum alpha 0.1 instead of 0.0 worked for me:
[UIView animateWithDuration:0.5
delay:0.0
options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse | UIViewAnimationOptionAllowUserInteraction
animations:^{
self.myButton.alpha = 0.1f;
}
completion:^(BOOL finished){
}]
Button registered the touchUpInside all the time with no additional method needed, and there was virtually no difference in appearance from taking the alpha to zero.
This won't work in iOS 3.2 since Blocks are only available in iOS4
you will have to use the standard animation techniques, in a separate thread so that you don't block the interface
[UIView beginAnimations:nil context:nil];
[UIView setAnimationTransition: UIViewAnimationTransitionFlipFromLeft forView:view cache:YES];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:1.0];
[view1 setHidden:TRUE];
[UIView commitAnimations];

Best method to get text to blink in iPhone OS?

I want my text box to blink (like the old LCD clocks).
Right now, I'm calling a myriad of NSTimers and selectors that wait, change the alpha, wait, then change it back. Even with this, it looks really bad, and I'm thinking I have to put an NSTimer to gradually change the alpha, but from what I hear they are not meant for things of that precision.
My thoughts are there must be a way to do this a lot better than how I am currently implementing it. It feels like hack.
Using an animation delegate might make it less "hacky":
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationDidStop:finished:context:)];
[myLabel setAlpha:0.0];
[UIView commitAnimations];
And then you can have your didStopSelector restart the animation:
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
[self displayLabel];
}
Depending on the animationID, you could take different actions, etc. Using UIView's setAnimationDelay might come in handy as well.
UIView also has a setDuration call for animations:
[UIView setAnimationDuration:0.1];
If you are building for iOS4, check the documentation since you should be using block-based animation calls rather than these delegate based ones.
you can set the alpha of the lable with annimation just like
to hide lable with animation
[UIView animateWithDuration:0.2 delay:0.1 options:UIViewAnimationOptionCurveEaseOut animations:^{
lblDistance.alpha=0;
} completion:^(BOOL finished) {
if (finished) {
}
}];
to show lable with animation
[UIView animateWithDuration:0.2 delay:0.1 options:UIViewAnimationOptionCurveEaseOut animations:^{
lblDistance.alpha=1;
} completion:^(BOOL finished) {
if (finished) {
}
}];
this is the best way anyone can animate and create a blinking lable........
I would use an NSTimer, but instead of messing with alpha channels i would either not draw the text (if that's even possible with Apple's very attribute-limited SDK), or if that's not possible you could always draw something on top of it (like a rectangle).
Using this approach of drawing something over your text would yield better performance.
Though some (okay most) would consider this a ugly hack, let me just say this, "If it looks right, it is right."
NSTimers and changing the alpha is a perfectly acceptable way of doing it - that's certainly what I do. If you are having problems, perhaps a code sample might help us see where the issue is?

Resources